【问题标题】:Model binding and display trimmed string property模型绑定和显示修剪后的字符串属性
【发布时间】:2010-01-18 10:04:13
【问题描述】:

我的强类型视图继承自使用 Linq to SQL 创建的“Person”对象。在我的“编辑”视图中,我当然必须显示旧值:

<%= Html.TextBox("FirstName") %>

“FirstName”是 NCHAR,所以需要修剪。所以我最终得到了:

<%= Html.TextBox("FirstName", Model.FirstName.Trim()) %>

这行得通。但是当提交表单时(在 POST 之后)并且出现一些错误,我需要再次显示它:

[AcceptVerbsAttribute(HttpVerbs.Post), Authorize(Roles = "office"), HandleError]
public ActionResult Edit(Models.Person person)
{
    if (!(_personService.ValidatePerson(person))) // Persona non valida
    { return View(person); }
}

如果由于某种原因用户离开文本框“FirstName”空白,则结果属性 Person.FirstName 将变为 null 并且 Model.FirstName.Trim() 会引发异常(对象引用未设置为对象的实例)。

有什么方法可以修改绑定并默认修剪所有字符串?或者对如何解决这个问题有任何想法

更新: 似乎已确认是 MVC 2 行为.. 仍在寻找处理此问题的好方法。实际使用扩展方法:

public static string TrimOrDefault(this string value)
{
    return value != null ? value.Trim() : string.Empty;
}

【问题讨论】:

  • @gremo 检查我对部分类示例的编辑。

标签: asp.net-mvc string binding trim defaultmodelbinder


【解决方案1】:

这里有些奇怪。

Model.FirstName 不应为空;模型绑定器足够聪明,可以将空输入字段(文本框)设置为“”。确保您的模型和您使用的文本框之间的属性名称匹配。

您使用的是哪个版本的 MVC? 1 还是 2?我在 VS 2008 中运行 MVC 1 版本,我可以让 FirstName 为空的唯一方法是根本不将它包含在表单中。

我可以看到您最初的 GET Edit 视图是否抛出了此错误,并且您在 dbml 和数据库中将 FirstName 设置为可为空,但由于它是一个 Post,这对我来说现在没有意义。 ;)

更新:

我已经确认了:

使用空表单:

  • VS 2008 - Mvc 1 - FirstName = ""
  • VS 2010 - Mvc 2 - FirstName = null

呃哦...那会破坏很多代码...

守则:

查看(两者相同):

<% using (Html.BeginForm()) {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="FirstName">FirstName:</label>
            <%= Html.TextBox("FirstName", Model.FirstName) %>
            <%= Html.ValidationMessage("FirstName", "*") %>
        </p>
        <p>
            <label for="LastName">LastName:</label>
            <%= Html.TextBox("LastName", Model.LastName) %>
            <%= Html.ValidationMessage("LastName", "*") %>
        </p>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

<% } %>

VS 2010 - Mvc 2

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

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

    public ActionResult AddPerson()
    {
        var person = new Person();

        return View(person);
    }

    [HttpPost]
    public ActionResult AddPerson(Person person)
    {
        return View(person);
    }
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

VS 2008 - Mvc 1

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

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


    public ActionResult AddPerson()
    {
        var person = new Person();

        return View(person);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult AddPerson( Person person )
    {

        return View(person);
    }
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

没有干净的修复自动取款机。模型绑定器实际上将这些属性设置为空。在构造函数中将 First 和 Last 设置为 "" 并从绑定中排除这些属性:[Bind(Exclude="FirstName, LastName")] 它们保持为 ""。

这是否记录在某个地方?

【讨论】:

  • 我正在考虑这个想法。您是否在将 person 对象传递给 Edit 方法时(即在它到达验证服务之前)对其进行了调试,以查看此时名字是 null 还是空?是否在验证服务中修改了人员对象并在那里设置为 null?您是否使用 Model.ModelState.AddModelError 将验证错误添加到模型状态?如果是这样,您是否也在使用 Model.ModelState.SetModelValue (它们成对工作,忽略 SetModelValue 会触发奇怪的空错误)。
  • Debuggin 显示 person 属性,例如提交后“LastName”为空(如果我在相应的文本框中将其设置为空白),就在代码的第一行之后。名称匹配。版本 2 vs 2010 beta 1。LastName in nchar(30) not null...谢谢
  • 这里有更多关于 null vs string.Empty 的内容:stackoverflow.com/questions/1263563/…
【解决方案2】:

【讨论】:

    【解决方案3】:

    在 Models.Person 中,默认值为 String.Empty,它至少应该消除 null 错误。

    如果您想让它自动化,那么您可以将它添加到您的 dbml 文件中。附加了一个designer.cs 文件,每个字段都有一个getter 和setter。如果您愿意,可以在其中添加代码。

    您还可以根据您的表格创建一个部分类并在其中处理修剪。这意味着如果您对 dbml 文件进行了更改,那么您的更改不会丢失。

    如果您不使用 dbml 文件,请告诉我们。

    编辑

    如果您的 dbml 文件中有一个名为 person 的类,那么它已经被声明为部分。

    在同一个项目中创建另一个类并执行以下操作;

    public partial class Person
    {
        public string NewName
        {
            get { return this._name.Trim(); }
        }
    }
    

    因此,从那时起,您可以使用 .NewName 代替 name,它会被修剪回来。您还可以在其中添加代码以确保它不是 null、不是红色、不是任何东西并返回适当的值。

    【讨论】:

    • 看起来不错,但我需要知道如何创建部分类。一般来说,我对 MVC 和 asp.net 真的很陌生……谁能指出我如何编辑 dbml 文件或创建部分类的正确方向?
    • 生成了designer.cs文件。修改它然后更改您的 dbml 意味着您的所有更改都消失了。
    • 是的,我说过!这就是为什么我添加了关于部分类的内容。
    【解决方案4】:

    我不知道这样做的扩展方法,如果其他人这样做,请告诉我。

    我为可能为空的字段创建了一个简单的 HTML 帮助器。

    public static string TrimOrDefault(string value)
    {
        return (value == null ? "" : value.Trim());
    }
    

    然后在你的代码中你可以使用

    <%= Html.TextBox("FirstName", Helpers.TrimOrDefault(Model.FirstName)) %>
    

    它可重复用于未来的可空字段并且易于读取。

    【讨论】:

    • 投下反对票。我相信您有解决方案,因此您投反对票?这实际上是一个可以接受的解决方案。
    • “有什么方法可以修改绑定并默认修剪所有字符串?”您的答案与模型绑定无关,仅与 HTML 输出有关。这次你给了他他已经使用的示例代码,只是使用扩展方法而不是 Trim():
    • “或者有什么解决方法的想法?”帮助器是处理可为空字段的简单解决方案。
    猜你喜欢
    • 1970-01-01
    • 2018-12-28
    • 2013-12-31
    • 2021-12-31
    • 1970-01-01
    • 2023-02-04
    • 1970-01-01
    • 2018-11-23
    • 2011-06-06
    相关资源
    最近更新 更多