问题
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();
}
...
回答1:
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
}
}
来源:https://stackoverflow.com/questions/8276627/how-can-i-build-a-custom-model-binder-which-will-return-different-types-of-model