1

I want to know, is there a way that I can pass an object(let's say a Message instance) from the validation in the model's fields and retrieve them from the ModelState( or by using some other thing) instance. Why I'm asking this is, I want to differentiate between the validation error message types so I can display only the messages I want in the view at a time. (Ex : required messages shown before the unique validation messages.)

I was trying to use a custom created Message object which I can then distinguish using its messageType field. But as the validation only returns string messages, can't think of a way.

4

1 回答 1

2

Are you ok with reading the messages out of ModelState and determining type based on message content? That can be done if you set a custom message for all the validations.

Then you can evaluate each message looking for specific content and take action. Such as putting the word "Error" in the Required attribute and Info in the rest.

Here's a class you can use to test

Model


public class EmployeeViewModel {

    public int ID { get; set; }

    [Display(Name = "First Name")]
    [Required(ErrorMessage = "Error")]
    public string FirstName { get; set; }

    [Display(Name = "Last Name")]
    [Required(ErrorMessage = "Error")]
    public string LastName { get; set; }

    [Display(Name = "Username")]
    public string Username { get; set; }

    [Display(Name = "Email Address")]
    public string EmailAddress { get; set; }
}

Controller


using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using TestApp.Models;

namespace TestApp.Controllers {

    public class HomeController : Controller {

        public ActionResult Index() {
            return RedirectToAction("Test");
        }

        public ActionResult Test() {
            var model = new EmployeeViewModel();
            return View(model);
        }

        [HttpPost]
        public ActionResult Test(EmployeeViewModel model) {
            // Force an error on this property - THIS should be the only real error that gets returned back to the view
            ModelState.AddModelError("", "Error on First Name");

            if(model.EmailAddress == null) // Add an INFO message
                ModelState.AddModelError("", "Email Address Info");
            if (model.Username == null) // Add another INFO message
                ModelState.AddModelError("", "Username Info");

            // Get the Real error off the ModelState
            var errors = GetRealErrors(ModelState);

            // clear out anything that the ModelState currently has in it's Errors collection
            foreach (var modelValue in ModelState.Values) {
                modelValue.Errors.Clear();
            }
            // Add the real errors back on to the ModelState
            foreach (var realError in errors) {
                ModelState.AddModelError("", realError.ErrorMessage);
            }
            return View(model);
        }

        private IEnumerable<ModelError> GetRealErrors(IEnumerable<KeyValuePair<string, ModelState>> modelStateDictionary) {
            var errorMessages = new List<ModelError>() ;
            foreach (var keyValuePair in modelStateDictionary.Where(keyValuePair => keyValuePair.Value.Errors.Count > 0)) {
                errorMessages.AddRange(keyValuePair.Value.Errors.Where(error => !error.ErrorMessage.Contains("Info")));
            }
            return errorMessages;
        }
    }
}

private IEnumerable<ModelError> GetRealErrors(IEnumerable<KeyValuePair<string, ModelState>> modelStateDictionary) {
    var errorMessages = new List<ModelError>() ;
    foreach (var keyValuePair in modelStateDictionary.Where(keyValuePair => keyValuePair.Value.Errors.Count > 0)) {
        errorMessages.AddRange(keyValuePair.Value.Errors.Where(error => !error.ErrorMessage.Contains("Info")));
    }
    return errorMessages;
}

View


@model TestApp.Models.EmployeeViewModel

<h2>Test</h2>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>EmployeeViewModel</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.FirstName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.FirstName)
            @Html.ValidationMessageFor(model => model.FirstName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.LastName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.LastName)
            @Html.ValidationMessageFor(model => model.LastName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Username)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Username)
            @Html.ValidationMessageFor(model => model.Username)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.EmailAddress)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.EmailAddress)
            @Html.ValidationMessageFor(model => model.EmailAddress)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
于 2012-06-06T01:43:09.563 回答