2017年8月2日 星期三

Custom Validation Error Message

Environment

  • VS 2015
  • DOT Net 4.5
  • C#
  • MVC


Background
You may want to custom the error message for support mulit-language


Original

Model:
public class ContactForm
{                
 [Required(ErrorMessage = "Your own custom message")]
 [Display(Name = "First Name")]
 public string FirstName { get; set; }

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

 [Required]
 [EmailAddress(ErrorMessage = "You must provide a valid email address")]
 [Display(Name = "Email Address")]
 public string EmailAddress { get; set; }
}

View:
@inherits System.Web.Mvc.WebViewPage<ContactForm>

<div id="fh5co-contact-section">
    <div class="container">         
  @{ Html.RenderAction("RenderContactForm", "Contact");}                    
    </div>        
</div>


Partial View:
@inherits System.Web.Mvc.WebViewPage<ContactForm>

<div id="formOuter">
    @using (Ajax.BeginForm("SubmitForm", "Contact", null, new AjaxOptions
    {
        HttpMethod = "POST",
        InsertionMode = InsertionMode.Replace,
        UpdateTargetId = "formOuter"
    }))
    {
        @Html.AntiForgeryToken()
        
        <div class="col-md-8 col-md-push-1 col-sm-12 col-sm-push-0 col-xs-12 col-xs-push-0">
            <div class="row">
                <div class="col-md-6">
                    <div class="form-group">
                        @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.FirstName, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="form-group">
                        @Html.TextBoxFor(m => m.LastName, new { @class = "form-control" } )
                        @Html.ValidationMessageFor(m => m.LastName, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="col-md-12">
                    <div class="form-group">
                        @Html.TextBoxFor(m => m.EmailAddress, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.EmailAddress, "", new { @class = "text-danger" })                        
                    </div>
                </div>
                <div class="col-md-12">
                    <div class="form-group">
                        @Html.TextAreaFor(m => m.Message, new { @class = "form-control", id = "", cols = "30", rows = "7" })
                        @Html.ValidationMessageFor(m => m.Message, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="col-md-12">                    
                    <br />
                    <div class="form-group">
                        <button value="Send Message" class="btn btn-primary use-ajax" type="submit">SendMessage</button>
                    </div>
                </div>
            </div>
        </div>
    }
</div>


Controller:
public ActionResult RenderContactForm()
{
 ContactForm model = new ContactForm();
 return PartialView("_ContactForm.cshtml", model);
}



After Implement Custom MetatdataProvider

Model:
public class ContactForm
{                
 [Required(ErrorMessage = "Your own custom message")]
 [Display(Name = "First Name")]
 public string FirstName { get; set; }

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

 [Required]
 [EmailAddress(ErrorMessage = "You must provide a valid email address")]
 [Display(Name = "Email Address")]
 public string EmailAddress { get; set; }


 public ContactForm()
 {
           ModelMetadataProviders.Current = new CustomModelMetadataProvider();
 }
}

public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
 private UmbracoContext _umbracoContext;
 public CustomModelMetadataProvider(UmbracoContext umbracoContext)
 {
  _umbracoContext = umbracoContext;
 }

 protected override ModelMetadata CreateMetadata(
              IEnumerable<Attribute> attributes,
              Type containerType,
              Func<object> modelAccessor,
              Type modelType,
              string propertyName)
 {

  var data = base.CreateMetadata(
           attributes,
           containerType,
           modelAccessor,
           modelType,
           propertyName);

  var description = attributes.SingleOrDefault(a => typeof(DescriptionAttribute) == a.GetType());
  if (description != null)
  {
   data.Description = ((DescriptionAttribute)description).Description;
  }

  
  foreach (ValidationAttribute attribute in attributes.OfType<ValidationAttribute>())
  {                
   attribute.ErrorMessage = "Your Own Message for each attribute";
  }

  return data;
 }
 
}

View:
No Change

Partial View:
No Change

Controller:
No Change

After Integrate with Umbraco

Model:
public class ContactForm
{
 #region private variable
 private UmbracoContext _umbracoContext;
 #endregion

 #region Form variable
 [Required]
 [Display(Name = "First Name")]
 public string FirstName { get; set; }

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

 [Required]
 [EmailAddress(ErrorMessage = "You must provide a valid email address")]
 [Display(Name = "Email Address")]
 public string EmailAddress { get; set; }

 [Required]
 [Display(Name = "Message")]
 public string Message { get; set; }
 #endregion
 
 public ContactForm(UmbracoContext umbracoContext)
 {
  _umbracoContext = umbracoContext;
  ModelMetadataProviders.Current = new CustomModelMetadataProvider(_umbracoContext);            
 }
}

public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
 private UmbracoContext _umbracoContext;
 public CustomModelMetadataProvider(UmbracoContext umbracoContext)
 {
  _umbracoContext = umbracoContext;
 }

 protected override ModelMetadata CreateMetadata(
              IEnumerable<Attribute> attributes,
              Type containerType,
              Func<object> modelAccessor,
              Type modelType,
              string propertyName)
 {

  var data = base.CreateMetadata(
           attributes,
           containerType,
           modelAccessor,
           modelType,
           propertyName);

  var description = attributes.SingleOrDefault(a => typeof(DescriptionAttribute) == a.GetType());
  if (description != null)
  {
   data.Description = ((DescriptionAttribute)description).Description;
  }

  
  foreach (ValidationAttribute attribute in attributes.OfType<ValidationAttribute>())
  {                
   attribute.ErrorMessage = GetDictionaryValue("Your Umbraco Dictionary Key", "en-US", _umbracoContext);;
  }

  return data;
 }
 
}


View:
@inherits UmbracoViewPage<ContactForm>

<div id="fh5co-contact-section">
    <div class="container">
        <div class="row">
            @{ Html.RenderAction("RenderContactForm", "Contact");}            
        </div>
    </div>    
</div>


Partial View:
@inherits UmbracoViewPage<ContactForm>

<div id="formOuter">
    @using (Ajax.BeginForm("SubmitForm", "Contact", null, new AjaxOptions
    {
        HttpMethod = "POST",
        InsertionMode = InsertionMode.Replace,
        UpdateTargetId = "formOuter"
    }))
    {
        @Html.AntiForgeryToken()
        
        <div class="col-md-8 col-md-push-1 col-sm-12 col-sm-push-0 col-xs-12 col-xs-push-0">
            <div class="row">
                <div class="col-md-6">
                    <div class="form-group">
                        @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.FirstName, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="form-group">
                        @Html.TextBoxFor(m => m.LastName, new { @class = "form-control" } )
                        @Html.ValidationMessageFor(m => m.LastName, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="col-md-12">
                    <div class="form-group">
                        @Html.TextBoxFor(m => m.EmailAddress, new { @class = "form-control" })
                        @Html.ValidationMessageFor(m => m.EmailAddress, "", new { @class = "text-danger" })                        
                    </div>
                </div>
                <div class="col-md-12">
                    <div class="form-group">
                        @Html.TextAreaFor(m => m.Message, new { @class = "form-control", id = "", cols = "30", rows = "7" })
                        @Html.ValidationMessageFor(m => m.Message, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="col-md-12">                    
                    <br />
                    <div class="form-group">
                        <button value="Send Message" class="btn btn-primary use-ajax" type="submit">SendMessage</button>
                    </div>
                </div>
            </div>
        </div>
    }
</div>


Controller:
public ActionResult RenderContactForm()
{
 ContactForm model = new ContactForm(_umbracoContext);
 return PartialView("_ContactForm.cshtml", model);
}


沒有留言:

張貼留言