【问题标题】:Razor view engine and model in html helpershtml 助手中的 Razor 视图引擎和模型
【发布时间】:2012-02-13 18:16:14
【问题描述】:

我正在尝试从这样的模型创建表单:

class NewContractorModel
{
    //...
    public PhotoModel photos { get; set; }
    //...
}
class PhotoModel
{
    public List<Photo> f { get; set; }
}

从控制器中,我对模型对象进行了一些操作(实际上我从集合中删除了一些照片),并使用以下方法将它们放入视图页面:

return new View("SomeView", model);

我尝试为每张照片创建输入(比如说隐藏输入)。

for (int i = 0; i < Model.photos.f.Count; ++i)
{
    @Html.HiddenFor(m => m.photos.f[i].Uri)
    @Html.HiddenFor(m => m.photos.f[i].ThumbnailUri)
    @Html.HiddenFor(m => m.photos.f[i].SmallThumbnailUri)
    @Html.TextBoxFor(m => m.photos.f[i].Description, new { placeholder = "Dodaj opis" })
}

但我注意到这不起作用,因为它取消了所有模型修改(尽管我已经在 Controler 方法中删除了它们,但它仍将所有照片存储在 List 中)。

然后我尝试了这段代码:

for (int i = 0; i < Model.photos.f.Count; ++i)
{
    Photo photo = Model.photos.f[i];
    <input id="photos_f_@{@i}__Uri" name="photos.f[@{@i}].Uri" type="hidden" value="@photo.Uri"/>
    <input id="photos_f_@{@i}__ThumbnailUri" name="photos.f[@{@i}].ThumbnailUri" type="hidden" value="@photo.ThumbnailUri"/>
    <input id="photos_f_@{@i}__SmallThumbnailUri" name="photos.f[@{@i}].SmallThumbnailUri" type="hidden" value="@photo.SmallThumbnailUri"/>
    <input id="photos_f_@{@i}__Description" name="photos.f[@{@i}].Description" placeholder="Dodaj opis" type="text" value="@photo.Description"/>
}

...这次成功了!

谁能解释一下这两部分代码有什么区别? 我已经尝试过 10 次以上的代码切换,但它总是以同样的方式工作,所以这不是我的错。 ;) 我认为 HtmlHelper 方法中存在一个错误,但有什么解决方法吗?我想使用辅助方法而不是原始 html。

编辑: 这是简化的控制器类。

public class MyController
{
    private NewContractorModel _model = null;

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        _model = SerializationUtility.Deserialize(Request.Form["Data"]) as NewContractorModel;
        if (_model == null)
                 _model = TempData["Data"]  as NewContractorModel;
        if (_model == null)
                 _model = new NewContractorModel() as NewContractorModel;

        TryUpdateModel(_model);
    }

    protected override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        if (filterContext.Result is RedirectToRouteResult)
            TempData["Data"] = _model;
    }

    private bool CheckModel(object model)
    {
        Type type = model.GetType();

        PropertyInfo[] properties = type.GetProperties();
        foreach (PropertyInfo p in properties)
        {
            object[] attr = p.GetCustomAttributes(true);
            foreach (object a in attr)
            {
                if (a is ValidationAttribute)
                {
                    object value = p.GetValue(model, null);
                    if (!((ValidationAttribute)a).IsValid(value))
                        return false;
                }
            }
        }
        return true;
    }

    protected ActionResult SelectPage(string delPhoto)
    {
        if (!CheckModel(_model))
        {
            // Do some action
        }
        //.....
        foreach (ZAY.Database.Photo p in _model.photos.f)
        {
            if (p.Uri == Request["delPhoto"])
            {
                _model.photos.f.Remove(p);
                break;
            }
        }
        //.....
        return View("SomeView", _model);
    }
}

我注意到在 lambdas 中,模型看起来就像调用 TryUpdateModel 之后(修改之前)。如果我不使用 lambda,模型会被修改...:/

还有我的 Photo 类(从 EntityFramework 生成 - 所以没有什么有趣的)并且也简化了:

public class Photo : EntityObject
{
    [Required]
    public string Uri { get; set; }

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

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

    public string Description { get; set; }
}

很抱歉,我只写了这么小的 sn-ps,但整个代码更复杂 - 只有其中最有趣的部分。

【问题讨论】:

  • 请发布您的 Photo 类定义和与此问题相关的控制器的 Action 方法。此外,如果您可以放置​​大部分视图(不仅仅是循环代码),那也会很有帮助。

标签: asp.net-mvc-3 razor html-helper


【解决方案1】:

这是我的问题的答案:

http://blogs.msdn.com/b/simonince/archive/2010/05/05/asp-net-mvc-s-html-helpers-render-the-wrong-value.aspx

我想知道为什么文档中没有提到它...:/

【讨论】:

    【解决方案2】:

    根据您的描述,我不太明白您的第一个示例中出了什么问题。但是你肯定对循环变量i的范围有问题。

    由于表达式m =&gt; m.photos.f[i] 涉及闭包,它将在稍后的时间进行评估,此时 for 循环已经完成。该表达式捕获变量i(而不是变量i 的值)。当它最终被评估时,它会在变量i 中找到值Model.photos.f.Count。所以所有隐藏的字段和文本框都将使用相同的无效值 i。

    您的第二个代码示例通过在 for 循环中使用局部变量来避免此问题。

    【讨论】:

    • 不,这不是问题,因为如果 i (0, 1, 2, 3, 4, ...),所有隐藏字段都有有效值。问题是当评估 lambda 以获取模型数据时......它使用了错误的模型对象:/不是我在 return View() 中设置为参数的这个对象。
    • 似乎“m => m...”(lambda 表达式)与简单的“Model...”(没有 lambda)的含义不同。这很奇怪。我也尝试为 Photo 类创建 EditorTemplate,然后调用 @Html.EditorFor(m => m.photos.f) 但它仍然给出相同的结果。
    猜你喜欢
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多