模型绑定和显示修剪的字符串属性

时间:2009-12-03 03:05:31

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

我的强类型视图继承自使用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;
}

4 个答案:

答案 0 :(得分:1)

这里有些奇怪。

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

您使用的是哪个版本的MVC? 1还是2?我在VS 2008中运行MVC 1版本,并且我将FirstName设置为null的唯一方法是不将其包含在表单中。

我可以看到你是否初始GET Edit视图引发了这个错误,并且你的dbml和数据库中的FirstName设置为可为空但由于它是一个帖子,这对我来说现在没有意义。 ;)

<强>更新

我已经证实了这一点:

使用空格式:

  • 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; }
}

没有干净的解决方法。模型绑定器实际上将这些属性设置为null。在构造函数中将First和Last设置为“”并从绑定中排除这些属性:[Bind(Exclude =“FirstName,LastName”)]它们保持“”。

这是在某处记录的吗?

答案 1 :(得分:1)

答案 2 :(得分:0)

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

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

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

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

修改

如果你的dbml文件中有一个名为person的类,那么这将被声明为partial。

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

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

所以从那时起你可以使用.NewName而不是名字,它会回来修剪。你也可以在那里添加代码以确保它不是空的,不是红色,不是什么,并返回适当的值。

答案 3 :(得分:-1)

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

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

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

然后在您的代码中,您可以使用

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

它可以在以后的可空字段中重复使用并轻松读取。