3

我有一个特定操作的传入请求(来自 Facebook 的 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); 
    }
}

FacebookPaymentsGetItemsRequest例如,如果传入的变量“方法”是“payments_get_items”并且FacebookPaymentsStatusUpdateRequest如果方法是“payments_status_update”并且我不知道如何在 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();
    }
    ...
4

2 回答 2

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
    }
}
于 2011-11-26T09:55:53.437 回答
0

DefaultModelBinder.NET Core 中似乎不存在。网络上的其他解决方案使用过时的类型ComplexTypeModelBinder。其中一些没有填写非共享字段。我花了几个小时尝试了一些东西。所以这是我的简单解决方案。

public class FacebookCreditModelBinder : IModelBinder
{
    private readonly ModelBinderProviderContext _providerCtx;

    // pass the ModelBinderProviderContext when 
    // creating this inside your IModelBinderProvider
    public FacebookCreditModelBinder(ModelBinderProviderContext providerCtx)
    {
        _providerCtx = providerCtx;
    }

    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
            throw new ArgumentNullException(nameof(bindingContext));

        // do some code to choose type
        var chosenType = typeof(FacebookPaymentsGetItemsRequest);

        // then do this
        var metadata = _providerCtx.MetadataProvider.GetMetadataForType(chosenType);
        var binder = _providerCtx.CreateBinder(metadata, _providerCtx.BindingInfo);
        bindingContext.ModelMetadata = metadata;
        return binder.BindModelAsync(bindingContext);
    }
}
于 2021-10-18T23:07:03.097 回答