ASP.NET Web API 中 symfony 的 paramconverter 等价物

symfony's paramconverter equivalent in ASP.NET Web API

我是.Net社区的新手,请手下留情哈哈。我有 两个问题:

  1. 在ASP.NET中是否有类似symfony's @paramconverter注解的实现(比如转换器属性)? 例如请求url,无论GET/POST/PUT/DELETE,带有id某个实体的api请求,我们能够convert/bind这样的id到一个实体对象中(在 int 中说 productId 并转换为 Product 对象)

预期的伪代码:

[Route("products/{productId}/comments")]
[ProductConverter]
public HttpResponseMessage getProductComments(Product product) {
    // product here not only with `productId` field, but already converted/bind into `Product`, through repository/data store
    ....
}
  1. 这是 .Net 中的良好做法吗?我要求这个实现是因为我认为这个模式能够减少重复代码,因为 API 请求主要依赖于对象 id。如果这样的字符串找不到这样的 Product 对象,我什至可以抛出异常。

看起来ModelBinder 相当于symphony 的parmconverter。您可以在这里阅读更多相关信息:http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

示例如下:

首先你必须实现 IModelBinder。这是它的非常基本的实现:

public class ProductBinder : IModelBinder
{

    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType != typeof(Product))
        {
            return false;
        }

        var id = (int)bindingContext.ValueProvider.GetValue("productId").ConvertTo(typeof(int));

        // Create instance of your object
        bindingContext.Model = new Product { Id = id };
        return true;
    }
}

接下来您必须配置 ASP.NET WebApi 以使用该活页夹。在 WebApiConfig.cs 文件(或您配置 WebAPI 的任何其他地方)添加以下行:

config.BindParameter(typeof(Product), new ProductBinder());

最后一步是创建正确的控制器方法。提供正确的路由参数以正确绑定很重要。

[Route("products/{productId}/comments")]
public HttpResponseMessage getProductComments(Product product) {

}

我不认为这是不好的做法或好的做法。一如既往,这取决于。可以肯定的是,它减少了代码重复并为您的代码引入了一些顺序。如果带有 id 的对象不存在,您甚至可以尝试将此活页夹调整为 return 响应 404(未找到)

编辑:

IModelBinder 与依赖注入一起使用有点棘手,但仍然可行。您必须编写额外的扩展方法:

public static void BindParameter(this HttpConfiguration config, Type type, Type binderType)
{
    config.Services.Insert(typeof(ModelBinderProvider), 0, new SimpleModelBinderProvider(type, () => (IModelBinder)config.DependencyResolver.GetService(binderType)));
    config.ParameterBindingRules.Insert(0, type, param => param.BindWithModelBinding());
}

它基于找到的原始方法 there。唯一的区别是它期望活页夹的类型而不是实例。所以你只需调用:

config.BindParameter(typeof(Product), typeof(ProductBinder));