ASP.NET mvc4 DropDownListFor传回一个对象

时间:2013-09-07 12:20:46

标签: c# .net asp.net-mvc

有没有办法告诉DropDownListFor回发一个对象而不是一个Id?我有以下代码:

public class Foo
{
    public int SelectedProductId { get; set; }

    public decimal MonthlyIncome { get; set; }

    public IEnumerable<Product> Products { get; set; }
}

@using(Html.BeginForm())
{
    @Html.DropDownListFor(x => x.SelectedProductId, new SelectList(Model.Products, "Id", "Name"))
    <input type="submit" value="Submit"/>
}

这很好用。但在我的模型中,我想要SelectedProduct而不是SelectedProductId。是否有可能告诉MVC传回一个对象实例而不是它的id?

感谢。

2 个答案:

答案 0 :(得分:4)

是的,当然,首先您需要确保SelectedProduct具有Id和Name属性,然后您必须使Model.Products返回SelectedProduct列表并覆盖SelectedProduct上的几个方法,如下所示:

    public override bool Equals(object obj)
    {
        var other = obj as ClientLookup;
        if (other == null)
            return false;

        return Id.Equals(other.Id);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }

    public override string ToString()
    {
        return Id.ToString();
    }

通过重写这些方法和ToString,您确保内部DropDownListFor将匹配Model.Products中的SelectedProduct与Foo中的当前SelectedProduct。

最后一块是ModelBinder,通过这种机制,您可以将http参数转换为在目标模型中设置的对象,对于SelectedProduct,您必须这样做:

public class SelectedProductModelBinder : IModelBinder
{

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        ValueProviderResult value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        SelectedProduct selectedProduct = new SelectedProduct();
        if (value.AttemptedValue != null && ! "".Equals(value.AttemptedValue))
            selectedProduct.Id = (int)value.ConvertTo(typeof(int));
        else
            selectedProduct.Id = null;

        return selectedProduct;
    }
}

现在不要忘记在应用初始化期间注册ModelBinder:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        ModelBinders.Binders.Add(typeof(SelectedProduct), new SelectedProductModelBinder());
    }
}

希望这有帮助。

答案 1 :(得分:0)

互联网是一个不受信任的区域。大多数人不希望能够像您所描述的那样从表单帖子中传回整个对象的数据。

例如,如果产品类具有价格值,则没有任何东西可以阻止某人篡改您的表单的回发值并将价格从100美元更改为1美元。

因此,大多数人只是传回对象标识并从可靠来源检索其值。

但是,如果您真的想在用户进行选择时回发整个产品,则可以使用产品的JSON编码表示作为选择框的值。