如何构建自定义模型绑定器,根据请求上下文返回不同类型的模型?

时间:2011-11-26 05:57:06

标签: asp.net-mvc-3 c#-4.0 custom-model-binder

我有来自具有不同内容的特定操作的传入请求(来自Facebook for Credits处理),因此我有不同的模型类来处理它。

这是我的行动:

public ActionResult Index([ModelBinder(typeof(FacebookCreditModelBinder))] IFacebookRequest facebookRequest)
{
    if (facebookRequest is FacebookPaymentsGetItemsRequest)
    {
        // do whatever
    }
}

这是我的模型活页夹。

public class FacebookCreditModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var binder = new DefaultModelBinder();
        // how to change the model here in the bindingContext?
        return binder.BindModel(controllerContext, bindingContext); 
    }
}

如果传入的var“方法”是“payments_get_items”,我想创建一个FacebookPaymentsGetItemsRequest对象,如果方法是“payments_status_update”,我想创建一个FacebookPaymentsStatusUpdateRequest,我不知道如何更改bindingContext中的模型类型。 是否可以在自定义模型绑定器中更改模型的类型?


其他方法:我也尝试使用BindModel并且我能够返回正确的对象但是所有属性都为null,因为它没有被默认的模型绑定器填充:

public override object BindModel(ControllerContext controllerContext,
        ModelBindingContext bindingContext)
{
    NameValueCollection form = controllerContext.HttpContext.Request.Form;
    if (form.Get("method") == "payments_get_items")
    {
        return new FacebookPaymentsGetItemsRequest();
    }
    ...

1 个答案:

答案 0 :(得分:5)

你可以这样做:

public class FacebookCreditModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var methodValue = bindingContext.ValueProvider.GetValue("method");
        if (methodValue == null || string.IsNullOrEmpty(methodValue.AttemptedValue))
        {
            throw new Exception("The method parameter was not found");
        }

        var method = methodValue.AttemptedValue;
        IFacebookRequest model = null;
        if (method == "payments_get_items")
        {
            model = FacebookPaymentsGetItemsRequest();
        }
        else if (method == "...")
        {
            model = ....
        }
        else
        {
            throw new NotImplementedException("Unknown method value: " + method);
        }

        bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType());
        return model;
    }
}

并在Application_Start注册:

ModelBinders.Binders.Add(typeof(IFacebookRequest), new FacebookCreditModelBinder());

然后您的控制器操作可能如下所示:

public ActionResult Index(IFacebookRequest facebookRequest)
{
    if (facebookRequest is FacebookPaymentsGetItemsRequest)
    {
        // do whatever
    }
}