1

我正在努力更好地理解和了解 MCV4。

将我的 Product 对象的属性 CategoryType 传递回 HttpPost 上的控制器的最佳方法是什么?

我正在寻找一种方法,因此我不必手动写出每个属性。我目前正在使用反射来迭代 Category 类型的属性,并使用 @Html.Hidden 方法将它们添加为隐藏输入变量。这可行,但我想知道我是否以正确的方式进行操作(最佳实践)。

  1. 我想知道如何使用@Html.HiddenFor 方法来实现我在下面所做的事情。我不知道如何使用反射中的属性信息编写 lambda 表达式。
  2. 有没有更好的方法来处理将 Category 对象传递给我的控制器。我的观点是强类型的。它是否应该知道在帖子中传回 Product 对象。

我有一个复杂的类型如下。

    public class Product
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string ProductName { get; set; }

    public Category CategoryType { get; set; }
}


public class Category
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string CategoryName { get; set; }
}

使用如下控制器

 public class ProductController : Controller
{
    //
    // GET: /Product/

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Add()
    {
        //Add a new product to the cheese category.
        var product = new Product();
        var category = new Category { Id = 1, CategoryName = "Cheese" };
        product.CategoryType = category;

        return View(product);
    }

    [HttpPost]
    public ActionResult Add(Product product)
    {
        if (ModelState.IsValid)
        {
            //Add to repository code goes here

            //Redirect to Index Page
            return RedirectToAction("Index");
        }
        return View(product);
    }
}

并使用 Add 视图

    @model BootstrapPrototype.Models.Product

@{
    ViewBag.Title = "Add";
}

<h2>Add</h2>


@using (Html.BeginForm())
{

    @Html.DisplayFor(m => m.ProductName);
    @Html.EditorFor(m => m.ProductName);

    foreach(var property in Model.CategoryType.GetType().GetProperties())
    {

        //I know how to use the Hidden but would also know how to use the HiddenFor with reflections.
        @Html.Hidden("CategoryType." + property.Name, property.GetValue(Model.CategoryType));
    }

    <button type="submit">Add</button>

}

谢谢。

4

2 回答 2

4

为什么隐藏?

我认为您将类别字段放在隐藏字段中的原因是因为您不希望用户更新它们,而且您需要将这些值作为对象的一部分返回Product,否则您的产品对象将在没有类别的情况下保存(null有价值)。这正是ViewModels 非常重要的原因。您创建一个视图模型,它接受您只需要的那些值的输入。因此,如果您需要创建一个只需要名称的产品,并且具有预先选择的不可编辑类别,那么您可以拥有一个视图模型:

public class ProductModel {
    public int Id {get;set;}
    public strnig Name{get;set;}
    public int CategoryId {get;set;}
}

和一个视图

@model ProductModel 
@Html.HiddenFor(m=>m.Id)
@Html.HiddenFor(m=>m.CategoryId)
@Html.TextboxFor(m=>m.Name)

您可以从控制器方法中获得

public ActionResult Add() {
    var product = new ProductModel {
        CategoryId = getIdFromDb("cheese");
    };
    return View();
}

您可以在控制器方法中接收

[HttpPost]
public ActionResult Add(ProductMOdel input) {
    // map input to an entity
    var productENtity = mapModelToEntity(input);
    // save entity to your repo
}

如果您的ProductCategory类中有一百个字段,则可以放大这种方法的这种优势。并且您有一个用例,其中只有部分字段将被编辑。

脚手架

但当然,您仍然可以按照自己的方式进行操作。但是,与其进行会产生开销的反射,不如摆脱它并做脚手架。以这种方式,您不必手动编码类的所有字段。这里有两个很好的链接可以帮助您开始使用脚手架:

使用反射

但是如果你坚持使用反射,那么它是完全有可能的(你几乎在你的代码中有它)

@foreach(var property in Model.CategoryType.GetType().GetProperties())
{
    @Html.Hidden("Product." + property.Name, 
        property.GetValue(Model.CategoryType));
}

该代码的关键是"Product."允许模型绑定器完成它的工作 - 隐藏字段中的值将被传递回您的 POST 控制器方法。但是,如果CategoryType为空,则该代码将不起作用。

于 2013-04-24T02:02:54.677 回答
0

我相信 MVC4 有HiddenInputAttribute。您可以将它与 Html.EditorFor 结合使用。

于 2017-02-08T21:18:04.220 回答