У меня есть команда, похожая на:
public interface ICommand {
// Just a marker interface
}
public interface IUserAware {
Guid UserId { get; set; }
}
public class CreateSomething : ICommand, IUserAware
{
public string Title { get; set; }
public Guid UserId { get; set; }
}
Запрос REST:
PUT /create HTTP/1.1
UserId: 7da6f9ee-2bfc-70b1-f93c-10c950c8f6b0 // Possible an Auth token and not a userId like here.
Host: localhost:63079
Content-Type: application/json
Cache-Control: no-cache
{
"title": "This is a test title"
}
У меня есть действие API-контроллера:
[HttpPut, Route("create")]
public IHttpActionResult CreateSomething([FromBody]CreateSomething command)
{
// I would like command.UserId already binded here
}
Свойство Title
в моей модели заполняется телом запроса, но я хотел бы привязать свойство command.UserId
, используя некоторые значения из заголовков запроса (например, из токена аутентификации).
Как связать свойство IUserAware
с значением заголовка запроса, например. образцовое связующее, без необходимости создания связующего для конкретного класса CreateSomething
?
Я пробовал различные комбинации интерфейса IModelBinder
в веб-API, но без реальной удачи.
Также кажется излишним использовать:
[HttpPut, Route("create")]
public IHttpActionResult CreateSomething([FromBody]CreateSomething command)
{
command.UserId = GetUserIdFromTheRequest();
}
Или получить UserId
из зависимости от контроллера и установить его, как указано выше.
Как это делается в ASP.NET MVC
В ASP.NET MVC можно выполнить следующие действия:
public class UserAwareModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, System.Type modelType)
{
var baseModel = base.CreateModel(controllerContext, bindingContext, modelType);
var commandModel = baseModel as IUserAware;
if (commandModel != null)
{
commandModel.UserId = controllerContext.HttpContext.User; // or get it from the HttpContext headers.
}
return baseModel;
}
}
И подключите его при запуске с помощью:
ModelBinders.Binders.DefaultBinder = new UserAwareModelBinder();