0

我知道如何创建一个镜像查询字符串变量的模型类,这样当它进入我的 Web API 控制器操作时,模型就会被填充。

但是,有没有办法让我不会将查询字符串变量名锁定为模型类的属性?

例子:

public class MyModel {
    public string o {get;set;}
}

public class MyController {
    public string Get(MyModel model) {

    }
}

然后,如果我的查询字符串如下所示: GET http://domain.com/?o=12345

有没有办法将该模型属性命名为“Order”或其他名称而不是“o”,然后用“o=”中的值填充它?

4

2 回答 2

1

您可以创建自定义模型绑定器,根据需要将数据绑定到模型。要使用它,您应该:

public string Get([ModelBinder(typeof(MyComplexTypeModelBinder))]MyModel model)
{
...
}

要创建自定义模型绑定器,您可以从 IModelBinder 或 DefaultModelBinder 继承。

public class MyComplexTypeModelBinder : IModelBinder
{

  public Object BindModel(ControllerContext controllerContext,
                          ModelBindingContext bindingContext)
  {
     if (bindingContext == null)
         throw new ArgumentNullException("bindingContext");

     // Create the model instance (using the ctor you like best)
     var obj = new MyComplexType();

     // Set properties reading values from registered value providers
     obj.Order = FromPostedData<string>(bindingContext, "o");
     ...
     return obj;
}


private T FromPostedData<T>(ModelBindingContext context, String key)
{
   // Get the value from any of the input collections
   ValueProviderResult result;
   context.ValueProvider.TryGetValue(key, out result);

   // Set the state of the model property resulting from 
   context.ModelState.SetModelValue(key, result);
   // Return the value converted (if possible) to the target type
   return (T) result.ConvertTo(typeof(T));
}
于 2012-12-05T05:21:09.477 回答
0

这种情况的解决方案是 custom IValueProvider。这个 ASP.NET MVC 扩展点是正确的地方,我们可以将QueryString键桥接到 Model.Property 名称中。与 相比ModelBinder,这将完全针对我们需要的内容(虽然不会引入以后的问题,即使其他值提供者 (FORM) 意外包含该键......)

有很好的教程如何介绍自定义IValueProvider

还有一个简单的例子,它能够为模型“Order”属性提供值,作为 QueryString“o”键:

工厂

// Factory
public class MyValueProviderFactory : ValueProviderFactory
{
  public override IValueProvider GetValueProvider(ControllerContext ctx)
  {
    return new MyValueProvider(ctx);
  }
}

提供者

// Provider
class MyValueProvider : IValueProvider
{
  protected HttpRequestBase Request { get; set; }    
  public MyValueProvider(ControllerContext ctx)
  {
    Request = ctx.HttpContext.Request;
  }

  // our custom logic to test QueryString keys, and expected prefixes
  public bool ContainsPrefix(string prefix)
  {
    var containsSpecial =
      "Order".Equals(prefix, StringComparison.OrdinalIgnoreCase)
      && Request.QueryString.AllKeys.Contains("o"
                    , StringComparer.InvariantCultureIgnoreCase);
    return containsSpecial;
  }

  // Handling "Order" key
  public ValueProviderResult GetValue(string key)
  {
    if (!ContainsPrefix(key))
    {
      return null;
    }
    var values = Request.QueryString.GetValues("o");

    if (values.Any())
    {
      return new ValueProviderResult(values, values.First()
                                    , CultureInfo.CurrentCulture);
    }
    return null;
  }
}

global.asax我们必须注入它:

protected void Application_Start()
{
  ValueProviderFactories.Factories.Add(new MyValueProviderFactory());
  ...
于 2012-12-05T07:13:14.567 回答