[英]How to set a default value from appsettings to a property on a API Model
[英]How to automatically set default value of API model's property with value from appSettings.json?
I'm creating a web API in Core 3.1 and I have PagingParams
model that I will use on many controller actions. model 有PageNumber
和PageSize
參數,這兩個參數都有一個默認值:
public class PagingParams
{
[Range(1, Int32.MaxValue, ErrorMessage = "The field {0} must be greater than 0.")]
public int? PageNumber { get; set; } = 1;
[Range(1, 10000)] //TODO: Get 10000 from appsettings
public int? PageSize { get; set; } = 10000; //TODO: Get 10000 from appsettings
}
PageSize
參數值需要設置為 10000 並且與其Range
屬性中的最大值相同。 這可以防止用戶每頁獲得超過 10k 個項目。
我希望能夠從appSettings.json
中檢索該值,這樣我就可以修改它而無需每次都重新發布應用程序。 在整個代碼中,我一直在使用IOptionsSnapshot
從appSettings.json
讀取值,但這里似乎無法完成,因為 model 需要具有無參數構造函數,導致以下錯誤:
System.InvalidOperationException:無法創建“WebAPI.Models.PagingParams”類型的實例。 Model 綁定的復雜類型不能是抽象類型或值類型,並且必須具有無參數構造函數。 或者,給“pagingParams”參數一個非空的默認值。
我如何設置 model 以便默認情況下從 appSettings 獲取int
並在兩個地方設置?
這就是 class 的使用方式:
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
private readonly IMapper _mapper;
private readonly IUserRepo _userRepo;
public MissingNamesController(IMapper mapper, IUserRepo userRepo)
{
_mapper = mapper;
_userRepo = userRepo;
}
[HttpGet]
public IEnumerable<UserDto> Get([FromQuery] UsersQueryParams queryParams, [FromQuery] PagingParams pagingParams)
{
IEnumerable<User> models = _userRepo.Get(queryParams, pagingParams);
IEnumerable<UserDto> dtoModels = _mapper.Map<IEnumerable<UserDto>>(models);
return dtoModels;
}
}
}
注意:我的問題類似於這個問題,除了我希望能夠設置它以使其自動化。 我想避免每次在操作上使用PagingParams
class 時調用方法,然后必須手動調用ModelState.IsValid
並返回 model 錯誤。 使用我當前的設置, Range
屬性會自動處理返回 model 錯誤,我不需要做任何進一步的事情。
您想要的是方便地使用一些默認值初始化一些屬性。 核心機制很簡單,就像您實例化 object 並在將其用於下一個管道之前設置其屬性。 有一些方法可以實現它:
通常你用第二種方法。 但是,為了盡可能避免重復代碼,我們需要在管道(代碼執行 - 請求處理流程)中找到一個點,您可以在其中獲取 object 並在一個地方初始化其屬性(從配置加載)。
在您的情況下, PagingParams
沒有在代碼中的任何地方實例化,這相當容易,它只是來自 controller 動作(由 model 綁定實例化)。 因此,在這種情況下,我們可以使用動作過濾器( IActionFilter
或IAsyncActionFilter
可以)作為我們可以獲得參數(類型為PagingParams
)並以我們想要的任何方式修改它(使用配置中加載的默認值初始化屬性)的點。
這很簡單:
public class InitPagingParamsAttribute : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
var pp = context.ActionArguments.Values.OfType<PagingParams>().FirstOrDefault();
//this means there is at least 1 PagingParams in the controller action
//NOTE that you can get all args of PagingParams, but looks like usually
//there should be just 1 arg of such type (in one same controller action)
if (pp != null)
{
//modify the pp here
//...
}
}
}
在Startup.cs
文件中,您可以配置 MVC 中間件以注冊全局操作過濾器。 如果不這樣做,您需要在 controller 或您想要的操作方法上裝飾屬性InitPagingParamsAttribute
。
public void ConfigureServices(IServiceCollection services){
//...
services.AddMvc(o => {
o.Filters.Add<InitPagingParamsAttribute>();
});
//...
}
注意:您可以在InitPagingParamsAttribute
構造函數中注入您的IOptionsSnapshot
。 因此,您可以從那里的配置中加載默認值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.