如何建立一个自定义模型粘合剂,它会根据请求上下文返回不同类型的模型? [英] How can I build a custom model binder which will return different types of models depending on the request context?
问题描述
我有传入的请求(来自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屋!