1

Is there any way to tell DropDownListFor to post back an object instead of an Id? I have the following code:

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"/>
}

and this works fine. But in my model, I want to have SelectedProduct instead of SelectedProductId. Is it possible to tell MVC to pass back an object instance instead of it's id?

Thanks.

4

2 回答 2

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());
    }
}

希望这可以帮助。

于 2013-09-07T12:53:46.133 回答
0

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

例如,如果一个产品类有一个价格值,那么没有什么可以阻止某人篡改表单的回发值并将价格从 100 美元更改为 1 美元。

因此,大多数人只是传回对象身份并从可信来源检索其值。

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

于 2013-09-09T03:44:59.717 回答