0

所以我的模型中有这个费用抽象类(由 EF 生成,并考虑到数据库优先)

public abstract partial class Fee
{    
    public int FeeId { get; set; }
    public int ProductId { get; set; }
    public string Name { get; set; }
    public decimal StandardPrice { get; set; }   
}

它被许多其他类继承以模拟不同类型的费用,例如 QuarterlyFee 之类的东西。我在模型中还有一个 Customer 类,客户可以有自定义费率,由 CustomerRate 类建模。

现在在客户详细信息页面上,我正在尝试显示客户的所有可能费用,以便用户可以选择哪些费率是自定义的,哪些是标准的,没有投标交易我只是创建一个 ViewModel 类 PossibleFee 来建模:

public class PossibleFee
{
    public int CustomerId { get; set; }
    public int FeeId { get; set; }
    public Boolean CustomRate { get; set; }
    public decimal CustomerPrice { get; set; }

    public virtual Customer Customer { get; set; }
    public virtual Fee Fee { get; set; }
}

我在 Customer 类中添加了一个属性来保存可能的费用(ICollection PossibleFees),我在 Controller 方法中填充该属性(public ActionResult Details(int id = 0)),稍后是一个 EditorTemplate,然后我有一个列表客户可能需要支付的所有费用,具体取决于用户可以编辑的产品。

但是现在在回发时,当我点击保存按钮时,默认模型绑定器会完成它的工作并尝试填充可能费用的 ICollection,并为每个可能费用尝试创建一个费用对象来填充同名的属性。

当然它不起作用,因为 Fee 是抽象的,问题很简单:我如何告诉 DefaultModelBinder 在回发时忽略该属性,因为我在回发时不需要它?

我知道我可以简单地在可能费的 EditorTenplate 类的可能费中重新复制我需要的字段,甚至可以从费中删除摘要。但我想知道是否可以在不接触模型的情况下根据需要调整 DefaultModelBinder。

编辑 2:在我看来,Yarx 提供了一个更清洁的解决方案,请参阅下面的 2 个帖子

编辑:好吧,Carlos Corral Carvajal 几乎做对了,在 ModelBinder 尝试创建对象后调用 SetProperty 方法,所以我不得不改写 BindProperty

public class CustomModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
    {            
        if (propertyDescriptor.Attributes.Contains(new ModelBinderIgnoreOnPostback()))
        {
            return;
        }

        base.BindProperty(controllerContext, bindingContext,propertyDescriptor);
    }
}

[AttributeUsage(AttributeTargets.Property, AllowMultiple=false, Inherited=false)]
public class ModelBinderIgnoreOnPostback : Attribute {}

添加了自定义属性以防有人需要它

4

2 回答 2

1

我的建议是将您的 ViewModel 分开,以便每个操作都有一个单独的 ViewModel。拥有一个仅用于显示信息的 ViewModel 和一个用于接受来自 Post Back 的信息的 ViewModel。因为在这种情况下,在用于显示数据的 ViewModel 中也需要在 PostBack 上绑定的大部分字段,最简单的做法是继承您的 ViewModel。例如,请参见下文。

public class PossibleFeeInputModel 
{
    public int CustomerId { get; set; }
    public int FeeId { get; set; }
    public Boolean CustomRate { get; set; }
    public decimal CustomerPrice { get; set; }

    public virtual Customer Customer { get; set; }
}

.

public class PossibleFeeViewModel : PossibleFeeInputModel
{
    public virtual Fee Fee { get; set; }
}

这样,您可以使用 PossibleFeeViewModel 来显示您的视图,但在您接受 PostBack 时使用 PossibleFeeInputModel 进行绑定。

于 2013-04-05T13:21:19.170 回答
0

您可以创建一个从默认模型绑定器继承的自定义模型绑定器,并捕获 Fee 类并对其执行特定操作:

public class CustomModelBinder : DefaultModelBinder
{

    protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
    {
        if (propertyDescriptor.PropertyType == typeof(Fee))
        {
            //Take desicions
        }

        base.SetProperty(controllerContext, bindingContext,
                            propertyDescriptor, value);
    }
}

在 global.asax 中:

ModelBinders.Binders.DefaultBinder = new CustomModelBinder();

希望能帮助到你

于 2013-04-05T11:15:16.397 回答