如何建立一个自定义模型粘合剂,它会根据请求上下文返回不同类型的模型? [英] How can I build a custom model binder which will return different types of models depending on the request context?

查看:114
本文介绍了如何建立一个自定义模型粘合剂,它会根据请求上下文返回不同类型的模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有传入的请求(来自Facebook的积分处理),其上会有有不同的内容,所以我有不同的模型类来处理特定的操作。

这是我的行动:

 公众的ActionResult指数([ModelBinder的(typeof运算(FacebookCreditModelBinder))] IFacebookRequest facebookRequest)
{
    如果(facebookRequest是FacebookPaymentsGetItemsRequest)
    {
        //做什么
    }
}

这是我的模型粘合剂。

 公共类FacebookCreditModelBinder:DefaultModelBinder
{
    公众覆盖对象BindModel(ControllerContext controllerContext,ModelBindingContext的BindingContext)
    {
        VAR粘结剂=新DefaultModelBinder();
        //如何在这里的BindingContext更改模型?
        返回binder.BindModel(controllerContext,BindingContext中);
    }
}

我想创建例如 FacebookPaymentsGetItemsRequest 对象,如果传入的无功的方法是payments_get_items和 FacebookPaymentsStatusUpdateRequest 如果方法是payments_status_update,我不知道如何改变的BindingContext模型的类型。
是否有可能改变模型的类型,在自定义模型绑定?


其他的办法:我BindModel试了一下还和我能够返回正确的对象,但所有属性都为空,因为它不是由默认的模型绑定填写:

 公众覆盖对象BindModel(ControllerContext controllerContext,
        ModelBindingContext的BindingContext)
{
    NameValueCollection中形式= controllerContext.HttpContext.Request.Form;
    如果(form.Get(办法)==payments_get_items)
    {
        返回新FacebookPaymentsGetItemsRequest();
    }
    ...


解决方案

您可以这样做:

 公共类FacebookCreditModelBinder:DefaultModelBinder
{
    保护覆盖对象CreateModel(ControllerContext controllerContext,ModelBindingContext的BindingContext,类型modelType)
    {
        VAR methodValue = bindingContext.ValueProvider.GetValue(办法);
        如果(methodValue == NULL || string.IsNullOrEmpty(methodValue.AttemptedValue))
        {
            抛出新的异常(以下简称方法参数未找到);
        }        VaR方法= methodValue.AttemptedValue;
        IFacebookRequest模型= NULL;
        如果(方法==payments_get_items)
        {
            模型= FacebookPaymentsGetItemsRequest();
        }
        否则如果(方法==...)
        {
            模型= ....
        }
        其他
        {
            抛出新NotImplementedException(未知方法的价值:+方法);
        }        bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(()=>模型,model.GetType());
        回归模型;
    }
}

和在注册的Application_Start

  ModelBinders.Binders.Add(typeof运算(IFacebookRequest),新FacebookCreditModelBinder());

那么你的控制器动作看起来是这样的:

 公众的ActionResult指数(IFacebookRequest facebookRequest)
{
    如果(facebookRequest是FacebookPaymentsGetItemsRequest)
    {
        //做什么
    }
}

I have incoming requests (from Facebook for Credits handling) on a specific action which will have have different contents, so I have different model classes to handle that.

This is my action:

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

And this is my model binder.

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); 
    }
}

I want to create for example a FacebookPaymentsGetItemsRequest object if the incoming var "method" is "payments_get_items" and a FacebookPaymentsStatusUpdateRequest if method is "payments_status_update" and I don't know how to change the type of the model in the bindingContext. Is it possible to change the type of the model in a custom model binder?


Other approach: I tried it with BindModel also and I'm able to return the correct object but all properties are null because it is not filled by the default model binder:

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

解决方案

You could do this:

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;
    }
}

and register in Application_Start:

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

Then your controller action could look like this:

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

这篇关于如何建立一个自定义模型粘合剂,它会根据请求上下文返回不同类型的模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆