ASP.NET MVC: Как я могу объяснить недопустимое нарушение типа конечному пользователю с HTML. ValidationSummary?

Серьезный n00b, предупреждающий здесь; щадите!

Таким образом, я закончил Ужин Компьютерного фаната Учебное руководство MVC, и я нахожусь теперь в процессе преобразования приложения VB.NET на ASP.NET MVC использование программы Ужина Компьютерного фаната как своего рода грубый шаблон.

Я использую "IsValid / GetRuleViolations ()" шаблон для идентификации входа недействительного пользователя или значений, которые нарушают бизнес-правила. Я использую LINQ для SQL и использую в своих интересах "OnValidate ()" рычаг, который позволяет мне выполнять проверку и выдавать исключение приложения после попытки сохранить изменения в базе данных через класс CustomerRepository.

Так или иначе все работает хорошо, за исключением того, что к тому времени, когда значения формы достигают моего метода проверки, недопустимые типы были уже преобразованы в или существующее значение по умолчанию. (У меня есть свойство "StreetNumber", которое является целым числом, хотя я предполагаю, что это было бы проблемой для DateTime или любых других нестрок также.)

Теперь, я предполагаю, что UpdateModel () метод выдает исключение и затем изменяет значение потому что HTML. ValidationMessage отображен рядом с полем StreetNumber, но мой метод проверки никогда не видит исходный вход. Существует две проблемы с этим:

  1. В то время как HTML. ValidationMessage действительно сигнализирует, что что-то неправильно, в HTML нет никакой соответствующей записи. ValidationSummary. Если бы я мог бы даже заставить сообщение об исключении разоблачать там указание на недопустимый бросок или что-то, что было бы лучше чем ничего.

  2. Мой метод проверки, который находится в моем Клиенте частичный класс, никогда не видит исходный ввод данных пользователем, таким образом, я не знаю, является ли проблемой недостающая запись или недопустимый тип. Я не могу выяснить, как я могу сохранить свою логику проверки хорошей и аккуратной в одном месте и все еще получить доступ к значениям формы.

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

Мне нужен новый шаблон проверки или есть ли некоторый способ передать исходные значения формы моему образцовому классу для обработки?


Код CustomerController

    // POST: /Customers/Edit/[id]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(int id, FormCollection formValues)
    {
        Customer customer = customerRepository.GetCustomer(id);

        try
        {
            UpdateModel(customer);

            customerRepository.Save();

            return RedirectToAction("Details", new { id = customer.AccountID });
        }
        catch
        {
            foreach (var issue in customer.GetRuleViolations())
                ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
        }
        return View(customer);
    }

1
задан Lucifer Sam 21 April 2010 в 22:17
поделиться

1 ответ

Это было бы хорошей отправной точкой: Скотт Гу - ASP.NET MVC 2: Проверка модели

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

Мой личный подход заключался бы в использовании моделей представления POCO с добавлением атрибутов проверки DataAnnotations для проверки (это упрощает подключение проверки на стороне клиента позже).Вы также можете создать собственные атрибуты ValidationAttributes для подключения к проверке привязки данных.

Если он действителен после привязки данных к вашему объекту POCO, передайте ему службу, которая выполняет более сложную бизнес-проверку. После того, как эта проверка пройдет, передайте ее другой службе (или той же службе), которая передает значения в объект вашего домена, а затем сохраняет их.

Я не знаком с шаблоном Linq to SQL GetRuleViolations, поэтому не стесняйтесь заменять один из моих шагов шаблоном, который подходит.

Я постараюсь объяснить это здесь.

Модель представления POCO:

public class EditCustomerForm
{
    [DisplayName("First name")]
    [Required(ErrorMessage = "First name is required")]
    [StringLength(60, ErrorMessage = "First name cannot exceed 60 characters.")]
    public string FirstName { get; set; }

    [DisplayName("Last name")]
    [Required(ErrorMessage = "Last name is required")]
    [StringLength(60, ErrorMessage = "Last name cannot exceed 60 characters.")]
    public string LastName { get; set; }

    [Required(ErrorMessage = "Email is required")]
    [RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                       @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                       @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$",
                       ErrorMessage = "Email appears to be invalid.")]
    public string Email { get; set; }
}

Логика контроллера

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, EditCustomerForm editCustomerForm)
{
    var editCustomerForm = CustomerService.GetEditCustomerForm(id);

    return View(editCustomerForm);
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, EditCustomerForm editCustomerForm)
{
    try
    {
        if (Page.IsValid)
        {
            //Complex business validation that validation attributes can't handle
            //If there is an error, I get this method to throw an exception that has
            //the errors in it in the form of a IDictionary<string, string>
            CustomerService.ValidateEditCustomerForm(editCustomerForm, id);

            //If the above method hasn't thrown an exception, we can save it
            //In this method you should map the editCustomerForm back to your Cusomter domain model
            CustomerService.SaveCustomer(editCustomerForm, id)

            //Now we can redirect
            return RedirectToAction("Details", new { id = customer.AccountID });
    }
    //ServiceLayerException is a custom exception thrown by
    //CustomerService.ValidateEditCusotmerForm or possibly .SaveCustomer
    catch (ServiceLayerException ex)
    {
        foreach (var kvp in ex.Errors)
            ModelState.AddModelError(kvp.Key, kvp.Value);
    }
    catch (Exception ex) //General catch
    {
        ModelState.AddModelError("*", "There was an error trying to save the customer, please try again.");
    }

    return View(editCustomerForm);
}

Ясно как грязь? Если вам нужны дополнительные разъяснения, просто дайте мне знать: -)

Опять же, это всего лишь мой подход. Вы могли бы просто подписаться на статью Скотта Гу, на которую я ссылался, а затем продолжить.

HTHs,
Чарльз

2
ответ дан 3 September 2019 в 01:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: