I am currently trying to figure out how to localize the error messages generated by MVC. Let me use the default model binder as an example, so I can explain the problem.
Assuming I have a form, where a user enters thier age. The user then enters "ten" in to the form, but instead of getting the expected error of
"Age must be beween 18 and 25."
the message
"The value 'ten' is not valid for Age."
is displayed.
The entity's age property is defined below:
[Range(18, 25, ErrorMessageResourceType = typeof (Errors),
ErrorMessageResourceName = "Age", ErrorMessage = "Range_ErrorMessage")]
public int Age { get; set; }
After some digging, I notice that this error text comes from the System.Web.Mvc.Resources.DefaultModelBinder_ValueInvalid in the MvcResources.resx file.
Now, how can create localized versions of this file?
As A solution, for example, should I download MVC source and add MvcResources.en_GB.resx, MvcResources.fr_FR.resx, MvcResources.es_ES.resx and MvcResources.de_DE.resx, and then compile my own version of MVC.dll?
But I don't like this idea. Any one else know a better way?
See http://forums.asp.net/p/1512140/3608427.aspx, scroll down to Brad Wilson's reply near the bottom of that page (Sat, Jan 09 2010, 3:20 PM). There are static properties on the DefaultModelBinder that you can set to localize the generic error messages.
The reason a generic error message is used instead of your [Range] message is that [Range] provides a validation error message, but this particular case is a binding error. There's absolutely no way the framework can ever hope to convert the string "ten" to an Int32, so it can't even fire the [Range] validator. This is what the "PropertyValueInvalid" key as mentioned in that forum controls.
In MVC3 do the following to change default messages:
add the App_GlobalResources folder to your ASP.NET site
add a new resource file, call it f.ex. MyResources.resx
add these keys
PropertyValueRequired: A value is required.
PropertyValueInvalid: The value '{0}' is not valid for {1}.
in Application_Start of global.asax.cs add the line DefaultModelBinder.ResourceClassKey = "MyResources";
Have you tried: IDataErrorInfo property
This article will help
Validating with the IErrorDataInfo
Interface (C#)
Related
I'm using a DetailsView for updating a record. If the edit input of some fields is too long, the system produces a "data will be truncated" exception.
I can see where I can detect the error in DetailsViewItemUpdating or DetailsViewItemUpdated, and provide a user message. However, I believe the visual feedback should be sufficient for this release, i.e. "hey, it didn't take my 30 characters, even though the header label said it would only allow 20".
Is there a way to force the DetailsView to do the truncation and accept the update?
Or some other approach to this data handling exception, which must be pretty common.
ANSWER: from Ammar Gaffar at EE:
Convert to template field
In EditItemTemplate
Set DataBindings > MaxLength property to desired max length of field
Works fine.
Can anybody tell me how to pass a value from one web form to another web form without using a query string and session?
You can pass the Values over different pages via QueryString like:
Response.Redirect("yourNextpage.aspx?identifier=DesiredValue");
On your next page you can retrieve the value like this:
Request.QueryString["identifier"];
Other Preferred way would be Server.Transer() and Postbackurl.
Refer this link for various possible ways.
there are several ways you can pass parameters between pages.
Using a Query String
Getting Post Information from the Source Page
Using Session State
Getting Public Property Values from the Source Page
Getting Control Information from the Source Page in the Same Application
for more detail visit followng link.
http://msdn.microsoft.com/en-us/library/6c3yckfw.aspx
You could use a Querystring in this case:
Page.Response.Redirect("show.aspx?id=1");
And then read it on the other end:
int id = Page.Request.QueryString["id"];
Using PostBackURL, ex:
PostBackUrl="~/result.aspx"
and on result.cs (Page Load)
lblEmployeeNumber.Text = HttpContext.Current.Request.Form["txtEmployeeNumber"];
With Session:
For example you login the system and your id is 123123123.
string userid = 123123123;
Session["userid"] = userid;
When you go another page/pages your session is alive when your session timeout.
<system.web>
<sessionState timeout="1250"/>
</system.web>
It seems what you're looking for is something like the flash-, view- or conversation scope in Java EE and Ruby on Rails.
For ASP.NET you could perhaps take a look at this one: Is there an equivalent of JSF #ViewScope in ASP MVC?
depends on type and how much information you wish to transfer. for instance, if you want to transfer some variable (strings or integer values) you consider to use querystring (you can found here major information). for instance, if you want to transfer typed objects (class instance) you consider to use session (you can found here major information).
Is it possible to write your own validator in grails that will return a valid object?
Something like:
static constraints = {
name(validator: {val, obj ->
if (Drink.findByName(val)) return [Drink.findByName(val)]
})
}
In other words - if the Drink already exists in the DB, just return the existing one when someone does a
new Drink("Coke")
and coke is already in the database
You cannot do this with a custom validator. It's not really what it was meant for. From the Grails Reference:
The closure can return:
null or true to indicate that the value is valid
false to indicate an invalid value and use the default message code
a string to indicate the error code to append to the "classname.propertName." string used to resolve the error message. If a field specific message cannot be resolved, the error code itself will be resolved allowing for global error messages.
a list containing a string as above, and then any number of arguments following it, which can be used as formatted message arguments indexed at 3 onwards. See grails-app/i18n/message.properties to see how the default error message codes use the arguments.
An alternative might be to just create a service method that 1) looks for the domain and returns it if it exists, 2) otherwise, saves the domain and returns it.
There's probably a more elegant alternative. Regardless, Grails' constraints mechanism isn't (and shouldn't be) capable of this.
Not sure if you can do this from inside the validator, but:
Drink d = Drink.findOrSaveWhere(name: 'Smooth Drink', alcoholLevel: '4.5')
i am using strut2.1.6 with tomcat 5.5
i have a Date field createDate in my PasswordHistory Bean, and corresponding date component on my "search.jsp" this field is optional - no validation required .
if i submit the form i am get the follwoing error on console
ognl.MethodFailedException: Method "setCreatedDate" failed for object com.security.data.PasswordHistory#d5b561 [java.lang.NoSuchMethodException: setCreatedDate([Ljava.lang.String;)] –
it looks that it is trying to convert the empty string to date, when it fails it tries to search the corresponding String argument method and if it converts the value to date successfully it calls the corresponding Date argument method – Muhammad Shahid
i want to avoid any conversion if the field is emtpy.
Do you have struts.devMode = true in struts.xml? From the docs:
And thirdly, perhaps the setting which is less widely known, and therefore a source of much confusion: it will raise the level of debug or normally ignorable problems to errors. For example: when you submit a field which cannot be set on an action 'someUnknownField', it will normally be ignored. However, when you're in development mode, an exception will be thrown, telling you an invalid field was submitted. This is very useful for debugging or testing large forms, but can also be confusing if you're relying on parameters in your request that are not set on the action, but which you are using directly in your view layer (warning: bad practice, you should always validate input from the web).
http://struts.apache.org/2.1.6/docs/devmode.html
To show this fundamental issue in .NET and the reason for this question, I have written a simple test web service with one method (EditString), and a consumer console app that calls it.
They are both standard web service/console applications created via File/New Project, etc., so I won't list the whole code - just the methods in question:
Web method:
[WebMethod]
public string EditString(string s, bool useSpecial)
{
return s + (useSpecial ? ((char)19).ToString() : "");
}
[You can see it simply returns the string s if useSpecial is false. If useSpecial is true, it returns s + char 19.]
Console app:
TestService.Service1 service = new SCTestConsumer.TestService.Service1();
string response1 = service.EditString("hello", false);
Console.WriteLine(response1);
string response2 = service.EditString("hello", true); // fails!
Console.WriteLine(response2);
[The second response fails, because the method returns hello + a special character (ascii code 19 for argument's sake).]
The error is:
There is an error in XML document (1, 287)
Inner exception: "'', hexadecimal value 0x13, is an invalid character. Line 1, position 287."
A few points worth mentioning:
The web method itself WORKS FINE when browsing directly to the ASMX file (e.g. http://localhost:2065/service1.asmx), and running the method through this (with the same parameters as in the console application) - i.e. displays XML with the string hello + char 19.
Checking the serialized XML in other ways shows the special character is being encoded properly (the SERVER SIDE seems to be ok which is GOOD)
So it seems the CLIENT SIDE has the issue - i.e. the .NET generated proxy class code doesn't handle special characters
This is part of a bigger project where objects are passed in and out of the web methods - that contain string attributes - these are what need to work properly. i.e. we're de/serializing classes.
Any suggestions for a workaround and how to implement it?
Or have I completely missed something really obvious!!?
PS. I've not had much luck with getting it to use CDATA tags (does .NET support these out of the box?).
You will need to use byte[] instead of strings.
I am thinking of some options that may help you. You can take the route using html entities instead of char(19). or as you said you may want to use CDATA.
To come up with a clean solution, you may not want to put the whole thing in CDATA. I am not sure why you think it may not be supported in .NET. Are you saying this in the context of serialization?