Проверка целочисленного поля с помощью пользовательского связывателя модели в ASP.NET MVC - PullRequest
1 голос
/ 03 марта 2010

Я столкнулся с проблемой, которая показалась мне интересной.

Возьмите форму ввода с полем ввода для целочисленного значения (в моем случае это стоимость). Я не хочу, чтобы "100 долларов" или "двадцать долларов" отправлялись в базу данных, так как они, скорее всего, будут жаловаться. Я хочу добавить ошибку в модель и отправить ее обратно пользователю. Казалось, просто;).

Я использую привязку пользовательской модели, потому что я использую наследование в моей доменной модели. У меня есть несколько типов событий, каждый из которых реализует IEvent, поэтому мне потребовался пользовательский механизм связывания моделей.

Проблема, с которой я сталкиваюсь, заключается в том, что, когда я пытаюсь связать поле стоимости и преобразование из строки в int завершается неудачно, я действительно не уверен, как лучше всего справиться с этим. *

Моя пользовательская модель Binder открытый класс EventModelBinder: IModelBinder { #region IModelBinder Members

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Trivial code ... binding other fields...

        _event.ProjectedCost = GetA<int>(bindingContext, "ProjectedCost").GetValueOrDefault(-1);

        return _event;
    }

    #endregion

    // From Scott Hanselman's blog :)
    private Nullable<T> GetA<T>(ModelBindingContext bindingContext, string key) where T : struct
    {
        if (String.IsNullOrEmpty(key)) return null;
        ValueProviderResult valueResult;
        Nullable<T> ret;
        //Try it with the prefix...
        bindingContext.ValueProvider.TryGetValue(bindingContext.ModelName + "." + key, out valueResult);
        //Didn't work? Try without the prefix if needed...
        if (valueResult == null && bindingContext.FallbackToEmptyPrefix == true)
        {
            bindingContext.ValueProvider.TryGetValue(key, out valueResult);
        }
        if (valueResult == null)
        {
            return null;
        }

        try
        {
            ret = (Nullable<T>)valueResult.ConvertTo(typeof(T));
        }
        catch
        {
            return null;
        }

        return ret;
    }

Это работает очень хорошо - если Enums равны нулю или не выбраны, я могу проверить их и сообщить пользователю, что это необходимо. Для поля стоимости я получаю -1, если конверсия не удалась. Но когда я проверяю данные на сервере и возвращаюсь к пользовательскому интерфейсу, поле Model.Event.ProjectedCost имеет значение null

Мой EventService

// ...
protected bool ValidateEvent(IEvent eventToValidate)
    {            
        if (eventToValidate.ProjectedCost < 0)
            _validationDictionary.AddError("ProjectedCost", "Incorrect format");

        return _validationDictionary.IsValid;
    }

    public bool SaveEvent(IEvent _event)
    {
        if (!ValidateEvent(_event))
            return false;
        try
        {
            _repository.SaveEvent(_event);
            return true;
        }
        catch
        {
            return false;
        }

My Edit.aspx View

<h2>Edit</h2>

<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>

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

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="ProjectedCost">ProjectedCost:</label>
            <%= Html.TextBox("ProjectedCost", Model.Event.ProjectedCost) %>
            <%= Html.ValidationMessage("ProjectedCost", "*") %>
        </p>

        <% Html.RenderPartial(String.Format("~/Views/Shared/{0}Form.ascx", Model.Event.Type), Model.Event, ViewData); %>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

<% } %>

<div>
    <%=Html.ActionLink("Back to List", "Index") %>
</div>

На мой взгляд, Model.Event.ProjectedCost имеет значение null, если не проверяется, что дает мне это (строка 54 является виновником):

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error:

Line 52:             <p>
Line 53:                 <label for="ProjectedCost">ProjectedCost:</label>
Line 54:                 <%= Html.TextBox("ProjectedCost", (Model.Event.ProjectedCost == null ? 0 : Model.Event.ProjectedCost)) %>
Line 55:                 <%= Html.ValidationMessage("ProjectedCost", "*") %>
Line 56:             </p>

Что бы я хотел сделать, это отправить значение, которое пользователь ввел обратно пользователю, но моя привязка пользовательской модели и / или логика проверки, похоже, устанавливают что-то в null?

Я понимаю, что это может быть не самый простой вопрос для чтения, поэтому дайте мне знать, если я смогу уточнить каким-либо образом!

Ответы [ 2 ]

1 голос
/ 03 марта 2010

Вы можете использовать javascript, чтобы ограничить ввод текстового поля только целыми числами.

0 голосов
/ 03 марта 2010

Похоже, что если вы сначала вызовете AddModelError без SetModelValue, вы получите иногда новые блестящие исключения NullReferenceExceptions:

http://www.crankingoutcode.com/?aspxerrorpath=/2009/02/01/IssuesWithAddModelErrorSetModelValueWithMVCRC1.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...