Некоторые поля не отображаются в ModelBinder

Ниже приведен код моего контроллера:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(int id, Actor actor)
    {

        try
        {
            actorRepository.Save(actor);
            return RedirectToAction("Index");
        }
        catch
        {
            return View("Edit");
        }
    }

Вызывающее представление имеет частичное представление, строго типизированное для класса Actor. По какой-то причине есть несколько полей, которые не привязаны к классу. Речь идет о полях Address, Address2 и ZipCode. Они заполняются на странице, но возвращаются нулевыми. Здесь есть все остальные поля, но только не эти.

Любые идеи? Кроме того, как я могу написать модульный тест, чтобы повторить это поведение?

Обновление публичного класса Actor {публичная строка MiddleName {get; набор;}

    [Required(ErrorMessage = "First Name is Required")]
    [RegularExpression(@"\w*", ErrorMessage = "Last Name Contains Illegal Characters")]
    public string FirstName { get; set; }

    [Required(ErrorMessage = "Last Name is Required")]
    [RegularExpression(@"\w*", ErrorMessage = "Last Name Contains Illegal Characters")]
    public string LastName { get; set; }

    [DataType(DataType.PhoneNumber, ErrorMessage = "Please Enter a Valid Phone Number")]
    [Required(ErrorMessage = "Phone Number is Required")]
    public string PhoneNumber { get; set; }

    [Required(ErrorMessage = "Address is Required")]
    [RegularExpression(@"\w*", ErrorMessage = "Address Contains Illegal Characters")]
    public string Address { get; set; }

    [RegularExpression(@"\w*", ErrorMessage = "Address2 Contains Illegal Characters")]
    public string Address2 { get; set; }

    [RegularExpression(@"\w*",ErrorMessage = "State Contains Illegal Characters")]
    [Required(ErrorMessage = "State is Required")]
    public string State { get; set; }

    [Required(ErrorMessage = "Zip Code is Required")]
    [RegularExpression("\b[0-9]{5}(?:-[0-9]{4})?\b",ErrorMessage = "Please Enter a Valid Zip Code")]
    public string ZipCode { get; set; }

    [Required(ErrorMessage = "Even in theater, you have to choose a gender")]
    public bool? Gender { get; set; }

    [Required(ErrorMessage = "Cell Phone Number is Required")]
    public string CellPhone { get; set; }

    public int ActorId { get; set; }

    [DataType(DataType.MultilineText, ErrorMessage = "Illegal Characters in Notes")]
    public string Notes { get; set; }

    [Required(ErrorMessage = "Email Address is Required")]
    [DataType(DataType.EmailAddress)]
    public string EMail { get; set; }

    [Required(ErrorMessage = "City Is Required")]
    public string City {get; set;}
}

<fieldset>
<legend>Fields</legend>
<p>
    <label for="MiddleName">MiddleName:</label>
    <%= Html.EditorFor(m=>m.MiddleName) %>
    <%= Html.ValidationMessage("MiddleName", "*") %>
</p>
<p>
    <label for="FirstName">FirstName:</label>
    <%=Html.EditorFor(m=>m.FirstName) %>
    <%= Html.ValidationMessage("FirstName", "*") %>
</p>
<p>
    <label for="LastName">LastName:</label>
    <%= Html.TextBox("LastName", Model.LastName) %>
    <%= Html.ValidationMessage("LastName", "*") %>
</p>
<p>
    <label for="PhoneNumber">PhoneNumber:</label>
    <%= Html.TextBox("PhoneNumber", Model.PhoneNumber) %>
    <%= Html.ValidationMessage("PhoneNumber", "*") %>
</p>
<p>
    <label for="Address">Address:</label>
       <%=Html.EditorFor(m=>m.Address) %>
       <%= Html.ValidationMessage("Address", "*") %>
</p>
<p>
    <label for="Address2">Address2:</label>
       <%=Html.EditorFor(m=>m.Address2) %>
    <%= Html.ValidationMessage("Address2", "*") %>
</p>
<p>
    <label for="State">State:</label>
    <%= Html.TextBox("State", Model.State) %>
    <%= Html.ValidationMessage("State", "*") %>
</p>
<p>
    <label for="ZipCode">ZipCode:</label>
    <%= Html.TextBox("ZipCode", Model.ZipCode) %>
    <%= Html.ValidationMessage("ZipCode", "*") %>
</p>
<p>
    <label for="Gender">Gender:</label>
    <%= Html.TextBox("Gender", Model.Gender) %>
    <%= Html.ValidationMessage("Gender", "*") %>
</p>
<p>
    <label for="CellPhone">CellPhone:</label>
    <%= Html.TextBox("CellPhone", Model.CellPhone) %>
    <%= Html.ValidationMessage("CellPhone", "*") %>
</p>
<p>
    <label for="ActorId">ActorId:</label>
    <%= Html.TextBox("ActorId", Model.ActorId) %>
    <%= Html.ValidationMessage("ActorId", "*") %>
</p>
<p>
    <label for="Notes">Notes:</label>
    <%= Html.TextBox("Notes", Model.Notes) %>
    <%= Html.ValidationMessage("Notes", "*") %>
</p>
<p>
    <label for="EMail">EMail:</label>
    <%= Html.TextBox("EMail", Model.EMail) %>
    <%= Html.ValidationMessage("EMail", "*") %>
</p>
<p>
    <label for="City">City:</label>
    <%= Html.TextBox("City", Model.City) %>
    <%= Html.ValidationMessage("City", "*") %>
</p>
<p>
    <input type="submit" value="Save" />
</p>
</fieldset>

person KevDog    schedule 01.11.2009    source источник
comment
Можете ли вы перечислить свое представление и определение объекта «Актер»?   -  person Rudy    schedule 01.11.2009
comment
Да, Actor - это класс POCO, и в этом представлении нет ничего экзотического (во всяком случае, о чем я знаю).   -  person KevDog    schedule 01.11.2009


Ответы (2)


Существует свойство ModelMetaData с именем ConvertEmptyStringsToNull (по умолчанию = true), который преобразует пустые строки в NULL в классе DefaultModelBinder ASP.MVC.

Вы можете изменить это с помощью DataAnnotation для каждого свойства следующим образом:

[DisplayFormat(ConvertEmptyStringToNull=false)]

или вы можете создать свой собственный ModelBinder и унаследовать его от DefaultModelBinder и просто переопределить метод GetPropertyValue, чтобы игнорировать этот параметр следующим образом:

ModelBinders.Binders.DefaultBinder = новый Delphi.Mvc.KeepStringsBinder (); ModelBinders.Binders.Add (typeof (ObjectBase), новый Delphi.Mvc.KeepStringsBinder ());

person Jared    schedule 30.01.2010

Вот как можно протестировать привязки моделей:

Как проверить пользовательские привязки моделей в ASP.NET MVC?

Только вы будете тестировать DefaultModelBinder.

Что касается полей, вы не показали исходный код Актера. Но поскольку вы говорите о полях, я предполагаю, что вы действительно используете поля, но связующие модели ASP.NET MVC не будут привязываться к полям - только к свойствам. Итак, если у вас есть

public class Actor
{
   public string ZipCode;
}

вам нужно будет изменить на

public class Actor
{
   public string ZipCode { get; set; }
}

Другая причина может заключаться в том, что у вас

public class Actor
{
   public Address Address { get; set; }
}

и вы используете частичное, чтобы показать адрес; поэтому он называется «ZipCode», но должен называться «Address.ZipCode». Или, может быть, в вашем Адресе нет конструктора без параметров ... Другими словами, не видя исходного кода, слишком многое можно догадаться.

С обновленной информацией это бессмысленно. Плохие поля выглядят так же, как и хорошие. Но попробуйте Html.TextBox вместо EditorFor. Попробуйте просмотреть данные POST с помощью FireBug (или IE Dev), проверьте правильность имен и значений полей. Если это так - проблема в подшивке модели, если они плохие / отсутствуют - что-то не так со страницей. Кроме того, попробуйте проверить ModelState.IsValid в действии вашего контроллера, а также ошибки ModelState.

person queen3    schedule 01.11.2009
comment
Я использую автоматические свойства, которые являются просто синтаксическим сахаром для полей на стороне реализации. Чуть позже, когда я написал пост, было уже очень поздно, и у меня не хватило мозгов, чтобы продолжать размещать код. - person KevDog; 01.11.2009
comment
Поля изначально были Html.TextBox, я переключил их на EditorFor, чтобы посмотреть, имеет ли это значение. Этого не произошло, и поскольку они одинаково отображаются на странице с использованием обоих методов, я в значительной степени исключаю это как причину. В качестве проверки я создал новое строго типизированное представление для метода Add и получил ту же ошибку с теми же полями. Пора копнуть глубже. - person KevDog; 01.11.2009