gpt4 book ai didi

c# - 如何传递 WebAPI Controller 数据,以便发布模型在绑定(bind)/反序列化或验证时具有访问权限

转载 作者:行者123 更新时间:2023-11-30 21:27:13 25 4
gpt4 key购买 nike

考虑这个 WebAPI Controller ,其中一些元数据在实例化时被检索。

public class MyController : ApiController
{
private readonly MetaData _metaData;

public MyController(IService service) // IService is injected via Unity Container DI
{
_metaData = service.GetMetaData();
}

[ValidateModel]
public IHttpActionResult Post([FromBody] PostModel model)
{
// do something
return new ResponseMessageResult(null);
}
}

假设 Post Action 的 PostModel 类定义如下:

public class PostModel : IValidatableObject
{
ComplexObject Data { get; set; }

[OnDeserialized]
internal void OnDeserialized(StreamingContext context)
{
// do something, using _metaData
}

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// validate, using _metaData
}
}

我希望我的 PostModel 能够在调用 OnDeserialized() 时理想地访问 MyController _metaData 对象,但我至少会满足于在执行 Validate() 时。

我考虑过:

  • ActionFilter- 不可能,因为模型绑定(bind)/验证发生在ActionFilter执行
  • Custom ValueProvider/ModelBinder——我想也许这些一起可以让我定义在 OnDeserialized() 中使用的 StreamingContext 并将其 Context 属性设置为 _metaData。但即使这是可能的,我也找不到正确的方法。
  • MessageHandler- 我认为每个路由的消息处理程序并不理想,但我可以使用依赖注入(inject)来检索 _metaData,然后...将此对象数据附加到已发布的数据?这感觉很老套,我对这种解决方案不是很热心。
  • 依赖注入(inject)——我可以在 PostModel 自己实例化期间为服务提供一个引用,但是 Controller 和模型位于不同的项目中,模型项目目前没有 Unity 容器依赖项。相反,它依赖于 Controller 项目和其他引用项目使用它们自己的 DI 来传递任何所需的数据。

也许有某种我不知道的操作级属性在这里对我有好处,或者以上之一是正确的?我必须相信有一种方法可以在反序列化过程中传递/访问动态服务器端数据,或者至少可以通过验证模型来传递/访问我只是不知道或想不到的正确方法。

两个附加说明:

  • 我正在使用 Asp.Net WebAPI,无法访问核心 WebAPI 属性、过滤器等。
  • Post Action 在 ProjectA 中,但 PostModel 在 ProjectB 中。 ProjectA 引用 projectB,但反之则不然。 ProjectB 目前不依赖于 Unity Container DI。

预先感谢您的帮助!

最佳答案

您可以使用 IModelBinder 来反序列化和验证您的 PostModel。这样做,您将可以在反序列化期间访问您的 Controller 实例。这段代码相当粗糙,但您应该明白了。

IModelBinder 实现

public class PostDataModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof(PostDataModel))
{
return false;
}

try
{
// Get the content of the request, deserialize into your model object
Task<string> bodyTask = actionContext.Request.Content.ReadAsStringAsync();
PostDataModel vm = JsonConvert.DeserializeObject<PostDataModel>(bodyTask.Result);

// Get an instance of your IService and get metadata
var service = (IService)actionContext.ControllerContext.Configuration.DependencyResolver.GetService(typeof(IService));
var metadata = service.GetMetadata();

// this is how you would get the Metadata directly from your controller as long as it was accessible
//var metadata = ((IMetadata)actionContext.ControllerContext.Controller).Metadata;

// do stuff with metadata to validate your object however you wish
vm.PopulateValidationErrors();

// return true if you were able to deserialize this object, false if you couldn't
return vm != null;
}
catch {
// do logging
return false;
}
}
}

将IModelBinder添加到WebApiConfig的Register方法中,全局使用IModelBinderconfig.BindParameter(typeof(PostDataModel), new PostDataModelBinder());

关于c# - 如何传递 WebAPI Controller 数据,以便发布模型在绑定(bind)/反序列化或验证时具有访问权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58140295/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com