Archive

Posts Tagged ‘Formatting’

HowTo: include MVC model property Display name in Required validation message

Just came across this validation error display in an MVC app I’ve recently started maintaining. The required input field validation seemed to not be localized, resulting in a mixed English and Greek (from the field’s Display name) message:

image

Looking at the MVC model I noticed they were using [Required] attributes for the userName and password properties, together with [Display(Name = "…")] for the displayed property title

public class LoginModel
  {
     [Required]
     [Display(Name = "Όνομα Χρήστη")]
     public string userName { get; set; }

     [Required]
     [DataType(DataType.Password)]
     [Display(Name = "Κωδικός")]
     public string password { get; set; }

     //…

That was changed to:

public class LoginModel
  {
     [Required(ErrorMessage = "Το {0} είναι απαραίτητο.")]
     [Display(Name = "Όνομα Χρήστη")]
     public string userName { get; set; }

     [Required(ErrorMessage = "Το {0} είναι απαραίτητο.")]
     [DataType(DataType.Password)]
     [Display(Name = "Κωδικός")]
     public string password { get; set; }

resulting in a fully localized validation error message with the respective property’s Display name auto-inserted in the validation ErrorMessage, thanks to the {0} used in the message string:

image

Note there’s also the lazy route like in this property:

[Display(Name = "Περίοδος Εγγύησης(Έτη):")]
[Required(ErrorMessage = "Απαραίτητο πεδίο")]
public int warrantyPeriod { get; set; }

where you just say something like “Required field” in the localized error message. This however will work only when you always show the error message next to the input field that fails to pass validation.

If you want to also show a validation summary say at the beginning and/or the end of the page (depending on where your submit button is), you’ll end up with an error summary that may just contain multiple entries of “Required field” text without any indication on what field it was (which would be practically useless that is).

Note that sometimes due to lack of space in a webpage (say if you have lots of input fields in a grid) you can only show say red “*” near input fields that have validation errors and explain them more in the tooltips and in an error summary control.

Even better you can use resource strings to avoid error message string duplication. That approach, though a bit more verbose as implemented in ASP.net means easier centralized maintenance and localization from a per locale/language resource file and less typos or slightly different error messages for the same thing. See example and related screenshots at https://stackoverflow.com/a/22849638

Advertisements

HowTo: format XML output of DataContractSerializer

based on the other samples posted at StackOverflow on how to format XML created by DataContractSerializer, that use XmlWriter, here’s a version (from ClipFlair source code) that works with streams (and Ionic.Zip library in specific).

It also shows how the code is when you don’t apply formatting (using conditional compilation).  Just comment out the #define (prefix it with //) to make it write unformatted XML.

 

#define WRITE_FORMATTED_XML

using System.Xml;

namespace ClipFlair.Windows
{

  public partial class BaseWindow : FloatingWindow
  {

    //...

    #if WRITE_FORMATTED_XML
    private static XmlWriterSettings XML_WRITER_SETTINGS = 
new XmlWriterSettings() { Indent=true, IndentChars=" "}; #endif //... public virtual void SaveOptions(ZipFile zip, string zipFolder = "")
//THIS IS THE CORE SAVING LOGIC { if (SavingOptions != null) SavingOptions(this, null); //notify any listeners View.Busy = true; try { ZipEntry optionsXML =
zip.AddEntry(zipFolder + "/" + View.GetType().FullName + ".options.xml", new WriteDelegate((entryName, stream) => { DataContractSerializer serializer =
new DataContractSerializer(View.GetType());
//assuming current View isn't null #if WRITE_FORMATTED_XML using (XmlWriter writer = XmlWriter.Create(stream, XML_WRITER_SETTINGS)) serializer.WriteObject(writer, View); #else serializer.WriteObject(stream, View); #endif })); } catch (Exception e) { MessageBox.Show("ClipFlair options save failed: " + e.Message); } finally { View.Busy = false; //in any case (error or not) clear the Busy flag } if (SavedOptions != null) SavedOptions(this, null); //notify any listeners } //... } }
%d bloggers like this: