ASP.NET 5: Is localization with DisplayAttribute gone? - localization

I am migrating an application from previous ASP.NET version to ASP.NET 5(vNext, MVC 6). Previously I localized forms with DisplayAttribute attached to ViewModel's properties:
[Required(ErrorMessageResourceName = "FieldIsRequired", ErrorMessageResourceType = typeof(Resources.Validation))]
[Display(Name = "UserName", ResourceType = typeof(Resources.Common))]
public string UserName { get; set; }
I added DataAnnotations service:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddViewLocalization(options => options.ResourcesPath = "Resources/Views")
.AddDataAnnotationsLocalization();
}
When I submit an invalid form, an error message gets localized (as specified in the [Required] attribute).
But trying to display the form, I got an exception (No public property "UserName" in the resource class), until I commented out [Display] attribute.
Seems like input labels can't be localized with [DisplayAttribute] anymore?
Thank you!

It is indeed gone. According to the documentation:
The runtime doesn’t look up localized strings for non-validation attributes. In the code above, “Email” (from [Display(Name = "Email")]) will not be localized.
Update 20.03.2017:
Localization of non-validation attributes was re-enabled with the new .NET Core SDK, according to the updated documentation:
DataAnnotations error messages are localized with IStringLocalizer<T>.
Using the option ResourcesPath = "Resources", the error messages in RegisterViewModel can be stored in either of the following paths:
Resources/ViewModels.Account.RegisterViewModel.fr.resx
Resources/ViewModels/Account/RegisterViewModel.fr.resx

Related

Asp.net core MVC post parameter always null

I am new to MVC core.
I have created a project with MVC core which has a controller. This controller has Get and Post action methods. If i pass data to Get method using query string it works fine, but when i pass complex JSON to post method, then it always shows me null.
Here what i am doing:
Post Request
URL: http://localhost:1001/api/users
Content-Type: application/json
Body:
{
"Name":"UserName",
"Gender":"Gender of the user",
"PhoneNumber":"PhoneNumber of the user"
}
Here is the Post action method
[HttpPost]
[Route("api/users")]
public async Task<IActionResult> Post([FromBody]User newUser)
{
...
}
When post request is called, then newUser always shows me null. And if i remove [FromBody] attribute then i receive newUser object but all of its fields are null.
Please help me and guide me in this issue.
EDITED
Here is my User class
public class User{
public int Id { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public string PhoneNumber { get; set; }
}
I had done same as described here for json data, but still receives null.
This could be because of how the null values are being handled. Set NullValueHandling to Ignore in AddJsonOptions and see if that works.
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddJsonOptions(jsonOptions=>
{
jsonOptions.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});
}
Note the original method Post([FromBody] User newUser)
For future readers from google, this same issue could arise if the method was Post(User newUser)
Note the lack of [FromBody]. This is a departure from previous versions of MVC where these parameters were generally inferred.
If you're an existing MVC5 developer who finds this page regarding AspNetCore.MVC, make sure to double check that you have [FromBody] decorated where relevant.
I created new ASP.NET Core project, added your functionality, and it works. Please, checkout this project on github.
Also, see screenshot of log with simple communication with this controller from browser console: Console output
Are you on Microsoft.AspNetCore.Mvc 1.0.0?
If you are, try sending this object as your body in a request (camel cased properties):
{
"name":"UserName",
"gender":"Gender of the user",
"phoneNumber":"PhoneNumber of the user"
}

Modify the default behavior of the properties of the models

My question isn't ASP.NET Remote Validation only on blur? because I asked to do with model properties.
I'm using a a model with properties, which are reflected in the client's web browser, and then, when I press the submit button, the ErrorMessages are printed in the web browser.
I want that when the client leave the input focused, no when I press the submit button, the server process the request (only the input "disfocused") and, in error case, show the ErrorMessage in the web browser.
My register model:
[DataType(DataType.EmailAddress)]
[Required(ErrorMessage = "El field {0} is obligatory.")]
[Display(Name = "Email")]
[StringLength(80, ErrorMessage = "Email too large.")]
[RegularExpression(#"^([a-zA-Z0-9._-]+)#(outlook|hotmail|yahoo)\.\w{2,}$", ErrorMessage = "Invalid email")]
public string Email { get; set; }
This can been done on the client side with
Layout page needs
#Render.Section("Scripts",required:false)
Your view would then have
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Your Bundle would be . This Bundle is added by default in a standard ASP MVC project in visual studio
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"
));
The view would then just need a #Html.ValidationMessageFor for each property
see more info here
ASP MVC validation

Sitecore PageEditor randomly shows error with Glass.Mapper

I sometimes receive an error when I open a page in page editor mode on my Sitecore site using Glass.Mapper.
You cannot save a class that does not contain a property that
represents the item ID. Ensure that at least one property has been
marked to contain the Sitecore ID. Type:
Castle.Proxies.IBasicPageProxy
at Glass.Mapper.Sc.Configuration.SitecoreTypeConfiguration.ResolveItem(Object
target, Database database)
at Glass.Mapper.Sc.GlassHtml.MakeEditable[T](Expression'1 field, Expression'1 standardOutput, T model, Object parameters,
Context context, Database database, TextWriter writer)
This appears in the place of the rendering, so it doesn't show up as a standard ASP error.
Restarting IIS solves this, but soon it appears again..
I use interfaces for model definitions, with every single interface inheriting from IBaseType:
[SitecoreType]
public interface IBaseType
{
[SitecoreId]
Guid Id { get; set; }
[SitecoreInfo(SitecoreInfoType.Name)]
string Name { get; set; }
[SitecoreItem]
Item InnerItem { get; set; }
[SitecoreInfo(SitecoreInfoType.Url)]
string Url { get; set; }
[SitecoreInfo(SitecoreInfoType.TemplateId)]
Guid TemplateId { get; set; }
[SitecoreInfo(SitecoreInfoType.FullPath)]
string FullPath { get; set; }
}
I use Sitecore 7.5 rev. 141003 (.NET 4.5, MVC5), and the latest versions of Glass.Mapper related NuGet packages currently:
Castle.Windsor 3.3.0
Castle.Core 3.3.3
Glass.Mapper 3.0.14.26
Glass.Mapper.Sc 3.2.3.46
Glass.Mapper.Sc.CastleWindsor 3.3.0.24
Glass.Mapper.Sc.Mvc-5 3.3.0.43
The issue appears on all machines we tried, but all of them uses Windows 8, IIS 8.5.9600. I tried reverting to the WebActivator method, but it didn't help. Model definitions are in a separate class library project, which references all glass mapper assemblies.
I'm pretty clueless, never run into this error before on other projects. Does anyone have any idea what can cause this, or how I could debug it?
Thank you for your help!
I have put below code in my model and it works
[SitecoreId]
public virtual Guid Id { get; set; }
Glass mapper requires Item to be represented by a ID. If the glass model does not have a property for GUID, you will see this error.
You can fix this by adding the property public virtual GUID Id {get; set;} to your glass model

Disable 'The value 'xxx' is not valid for 'yyy' message

In my ASP.NET MVC application, I have a form and I'm using a ViewModel, so the ModelBinder can bind to my Strongly Typed Class. I'm using DataAnnotations for validation
public class FormViewModel
{
[Required]
public string SomeValue {get;set;}
[Range(0, 10, ErrorMessage="Enter a number between 0 and 10.")]
public byte? SomeOtherValue {get;set;}
}
This works great. The problem however is when the user doesn't enter a valid value for the SomeOtherValue (like abc), a standard MVC-error pops up: 'The value 'abc' is not valid for 'SomeOtherValue'. This is really annoying, as I can't customize this message. I know there are ways to Localize this message, but that just doesn't make sense (I don't want a general message, I want a value-specific value).
I tried applying a RegularExpression-attribute to the 'SomeOtherValue', which only allows byte-values, but probably the standard-validation 'overrides' this validation. Is there some way to apply a custom 'the value is not valid' message for a property, or otherwise disable the standard-message?
Here is a different (non-ideal way, IMHO) to fix it if the custom validation attribute is not working for you. In the controller:
if (!ModelState.IsValid)
{
string fieldName = "ThatFieldName";
var m = ViewData.ModelState[fieldName];
if (m != null && m.Errors.Count > 0)
{
ViewData.ModelState.Remove(fieldName);
ViewData.ModelState.AddModelError(fieldName, "You mucked that field up.");
}
}

asp.net mvc validation must be a number custom error

I am new to asp.net and I have a problem. When the users insert in a editor for a decimal field something other than numbers, they get an error "Field name" is not a number. But I don't want them to receive this message I want them to receive another message. I have no problem with this with required and range validators.
Is there any way for me to do this?
I am not refering necessarily to changing the culture just displaying another message.
Thanks.
Hope I understand your, to change RangeValidator ErrorMessage just initialize ErrorMessage parameter:
[Range(0, 100, ErrorMessage = "Some another error message insert here!")]
[RegularExpression("\d", ErrorMessage = "!!!")]
public decimal DecimalField { get; set; }
This is the actual answer:
Create a class CustomClientDataTypeModelValidatorProvider. Copy the code from the MVC sources. Change the method MakeErrorString to output the appropiate message like this:
private static string MakeErrorString(string displayName)
{
return string.Format(
CultureInfo.CurrentCulture,
Core.Resources.Errors.EroareNuENr,
displayName);
}
I couldn't find a way not to copy the code just extend it as it uses this static method.
If anyone knows this please tell me.
Then, in global.asax, I wrote this:
var cdProvider = ModelValidatorProviders.Providers.SingleOrDefault(p => p.GetType().Equals(typeof(ClientDataTypeModelValidatorProvider)));
if(cdProvider != null)
{
ModelValidatorProviders.Providers.Remove(cdProvider);
ModelValidatorProviders.Providers.Add(
new CustomClientDataTypeModelValidatorProvider());
}
so that the flow would actually be routed to my class and not the class in the asp.net MVC dll
I got the idea from here:
Unfortunately this is is not a trivial task. However you can try the following hack...
Better to do this only on essential fields, as this is more code to maintain.
In the controller's action method
if(ModelState.IsValid)
{
// code
}
else
{
if (ModelState["YourField"].Errors.Count > 0)
{
ModelState["YourField"].Errors.Clear();
ModelState.AddModelError("YourField", "Your custom message here");
}
// code
}
You can set ResourceClassKey of ClientDataTypeModelValidatorProvider class to name of a global resource that contains FieldMustBeNumeric key to replace mvc validation error message of number with your custom message. Also key of date validation error message is FieldMustBeDate.
ClientDataTypeModelValidatorProvider.ResourceClassKey="MyResources"; // MyResource is my global resource
See here for more details on how to add the MyResources.resx file to your project:
The field must be a number. How to change this message to another language?
To change the error message you get after server side validation you need to change 'PropertyValueInvalid' key in your resource file and assign the resource file name to DefaultModelBinder.ResourceClassKey. See this question for details: localize default model validation in mvc 2
Look for solution at the end of this page:
http://jwwishart.wordpress.com/2010/03/22/custom-server-and-client-side-required-validator-in-mvc-2-using-jquery-validate/
I checked this in my MVC 3 RTM project and it works well.
... or use jQuery to change to message on the client.
A quick and simple hack for Customize RangeValidator ErrorMessage --"'Field name' is not a number"-- is using RegularExpression
[Range(0.5, 1000, ErrorMessage = "Amount should be in range {1} to {2}.")]
[DataType(DataType.Currency)]
[RegularExpression(#"\d", ErrorMessage = "Amount is not valid.")]
public decimal Amount{ get; set; }
You could implement your own custom validation attribute: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
It seems that since Para's answer MVC evolved and now the ClientDataTypeModelValidatorProvider accepts a ResourceClassKey property. It uses the FieldMustBeNumeric and FieldMustBeNumeric messages specified in your resource class.

Resources