Tag Archives: mvc

Localizing Default Error Messages in MVC

Recently in a (non-english) project i’m working on, I was surprised with the following message “The value ‘150000.00’ is not valid for Preço.”.  I thought that my project was already localized to Portuguese, but apparently no.

mvc

The problem is related with some messages that can’t be localized using validation attributes Like the RequiredAttribute found in System.ComponentModel.DataAnnotations namespace.

Ex:

[Required(ErrorMessageResourceName = "ValidacaoObrigatoria", ErrorMessageResourceType = typeof(MyProject.Properties.Resources))]
public int Prop1 { get; set; }

Messages like “The value ‘{0}’ is not valid for {1}” need a different approach.
For localize default error messages in MVC we will need to add the following code to the Global.asax Application_Start method.

DefaultModelBinder.ResourceClassKey = "ValidationResources";
ClientDataTypeModelValidatorProvider.ResourceClassKey = "ValidationResources";

Where “ValidationResources” is the the name of the resource file (class key) that contains localized string values.
Next create a resource file name ValidationResources.resx or ValidationResources.fr.resx or whatever culture you need to support, mark it embeded inside App and add the following:

FieldMustBeDate The field {0} must be a date.
FieldMustBeNumeric The field {0} must be a number.
PropertyValueInvalid The value ‘{0}’ is not valid for {1}.
PropertyValueRequired A value is required.

My translation to Portuguese will be something like this:

PropertyValueInvalid O valor ‘{0}’ não é válido para o campo ‘{1}’.
FieldMustBeDate O campo ‘{0}’ deve ser uma data válida.
FieldMustBeNumeric O campo ‘{0}’ deve ser um número válido.
PropertyValueRequired O preenchimento deste campo é obrigatório.

Note:
The resource file should be added to the App_GlobalResources folder.

Digg thisBuffer this pageShare on FacebookShare on Google+Share on LinkedInPin on PinterestShare on RedditShare on StumbleUponShare on TumblrTweet about this on Twitter

MVC 5 Signout Fails

Recently I came across with a problem in the LogOff method that is generated with a new MVC 5 solution.

mvc

The problem was:

  • User1  logged in  and Login method is called in the Account controller.
  • User1 logs off and the LogOff method is called in the Account controller and the following code is executed:
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    {
        AuthenticationManager.SignOut();
        return RedirectToAction("Login", "Account");
    }
    
  • User2 logged in  and Login method is called in the Account controller. After this the User1 is logged in instead of User2.

It seems this is a known issue where the explicit sign-in is preferred over a generic sign-out with no params. The solution is change the  call to SignOut and pass the AuthenticationType of the cookie, and this will override the explicit sign-in.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie, DefaultAuthenticationTypes.ExternalCookie);
    return RedirectToAction("Login", "Account");
}
Digg thisBuffer this pageShare on FacebookShare on Google+Share on LinkedInPin on PinterestShare on RedditShare on StumbleUponShare on TumblrTweet about this on Twitter

MVC bundle EnableOptimizations

Bundling and minification are two techniques you can use to improve request load time.

Bundling is a ASP.NET 4.5 feature to combine multiples files into a single file. This is used in CSS and JavaScript files.
Minification performs code optimizations (ex: remove comments) to CSS and JavaScript files to reduce size.

Bundling and minification are enabled or disabled by default by setting to true or false the Compilation element.

mvc

To change this behavior use the BundleTable.EnableOptimizations property and set to true to enable bundling and minification.

Many times in a production environment you need something else to control the bundling and minification especially when you need to diagnose a problem in your JavaScript.

You can use any logic you want or, for a simple scenario, use a app settings key.

ex:

BundleTable.EnableOptimizations = bool.Parse(System.Configuration.ConfigurationManager.AppSettings["EnableOptimizations"]);

Place this code in your BundleConfig class inside method RegisterBundles.

Digg thisBuffer this pageShare on FacebookShare on Google+Share on LinkedInPin on PinterestShare on RedditShare on StumbleUponShare on TumblrTweet about this on Twitter

Mvc DisplayAttribute Name based on resources

If you try to use resources in the property Name like this:

    public class ForgotViewModel
    {
        [Required]
        [Display(Name = Resources.Email)]
        public string Email { get; set; }
    }

You will get the error “An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type”

And this error is correct. So to use resources you will have to do something like this:

    public class ForgotViewModel
    {
        [Required]
        [Display(Name = "Email", ResourceType=typeof(Resources))]
        public string Email { get; set; }
    }

Now in your Resources type you will have to make sure that the Email property exists and that it’s Access Modifier is Public.

To may all Resources Public double click in your resx files and locate the drop box “Access Modifier” and change it’s value to Public.

 

Digg thisBuffer this pageShare on FacebookShare on Google+Share on LinkedInPin on PinterestShare on RedditShare on StumbleUponShare on TumblrTweet about this on Twitter

Mvc5 EmailService implementation

This my generic EmailService Implementation. From here I can configure any email service like gmail.

public class EmailService : IIdentityMessageService
    {
        private const string ConfigurationEmailIsBodyHtml = "EmailIsBodyHtml";

        public static string From { get; set; }
        public static string UserName { get; set; }
        public static string Password { get; set; }
        public static string Host { get; set; }
        public static int Port { get; set; }
        public static bool EnableSsl { get; set; }
        public static bool IsBodyHtml { get; set; }
        public static bool UseDefaultCredentials { get; set; }
        public static SmtpDeliveryMethod DeliveryMethod { get; set; }

        static EmailService()
        {
            IsBodyHtml = ConfigurationManager.AppSettings[ConfigurationEmailIsBodyHtml].ToOrOther<bool>(true);

            SmtpSection section = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp");

            if (section != null)
            {
                From = section.From;
                Host = section.Network.Host;
                Port = section.Network.Port;
                EnableSsl = section.Network.EnableSsl;
                UserName = section.Network.UserName;
                Password = section.Network.Password;
                DeliveryMethod = section.DeliveryMethod;
                UseDefaultCredentials = section.Network.DefaultCredentials;
            }

        }

        public Task SendAsync(IdentityMessage message)
        {

            var smtp = new SmtpClient
            {
                Host = Host,
                Port = Port,
                EnableSsl = EnableSsl,
                DeliveryMethod = DeliveryMethod,
                UseDefaultCredentials = UseDefaultCredentials,
                Credentials = new NetworkCredential(UserName, Password)
            };

            using (var smtpMessage = new MailMessage(From, message.Destination))
            {
                smtpMessage.Subject = message.Subject;
                smtpMessage.Body = message.Body;
                smtpMessage.IsBodyHtml = IsBodyHtml;
                return smtp.SendMailAsync(smtpMessage);
            }

            // Plug in your email service here to send an email.
            //return Task.FromResult(0);
        }
    }

Gmail configuration:

  <system.net>
    <mailSettings>
      <smtp deliveryMethod="Network" from="[email protected]">
        <network host="smtp.gmail.com"
                 port="587"
                 enableSsl="true"
                 defaultCredentials="false"
                 userName="[email protected]"
                 password="password"/>
      </smtp>
    </mailSettings>
  </system.net>

 

Digg thisBuffer this pageShare on FacebookShare on Google+Share on LinkedInPin on PinterestShare on RedditShare on StumbleUponShare on TumblrTweet about this on Twitter