How do you implement a culture-specific address form using ASP.NET MVC?
We currently have a WebForms control with an update panel. The code-behind contains logic to show/hide fields based on the s开发者_运维技巧elected country. This is fine for WebForms, but we ware moving to MVC, and I'm having a hard time sorting this out. I also need this to be localized, both in terms of localizable resource strings as well as displaying different form fields for different countries.
We currently store the resource strings in a .resx file in a Resources folder. Our address fields per country is stored in an XML doc that we load and parse when the country changes. This is then used to locate the respective controls and show/hide those necessary. The last bit I'm trying to work out is validation messages. Reflection doesn't work on Resource classes, and I don't know of any utilities to allow variables in an attribute definition.
I've thought of using an XSL transform to create the address bit from our persisted address fields. Is that a valid approach?
You should still be able to output the correct language text just by reaching into the resource itself. A helper method might make it easier to type / more readable, but that will get you your form properly.
For displaying different controls, you could create a partial that pertains to a particular country, and load those up dynamically, something like:
<%= Html.RenderPartial("_addressForm-" + countryCode) %>
Again, a helper method might make this easier / more transparent.
Lastly, what type of validation are you using? The built-in MVC2 validation attributes off of a a view model? If so, I believe this is built-in to the attributes that you use to specify required fields, etc.
Hope this helps.
I discovered I was trying to use reflection incorrectly against my resource type and was able to create a few methods to get the correct resource:
public string GetLabel(string control)
{
string strResourceName;
try
{
AddressInfoField field = AddressFields.First(f => f.m_strControl == control);
strResourceName = field.m_strName;
}
catch // Catch everything
{
return string.Empty;
}
if (string.IsNullOrEmpty(strResourceName))
return string.Empty;
return GetResource(strResourceName);
}
public string GetValidationMessage(string control)
{
string strResourceName;
try
{
AddressInfoField field = AddressFields.First(f => f.m_strControl == control);
strResourceName = field.m_strName;
}
catch // Catch everything
{
return Addressing.Required;
}
if (string.IsNullOrEmpty(strResourceName))
return Addressing.Required;
return GetResource(strResourceName + "Required");
}
private static string GetResource(string strResourceName)
{
PropertyInfo property = typeof (Addressing).GetProperty(strResourceName, BindingFlags.Public | BindingFlags.Static);
if (property == null)
throw new InvalidOperationException("Could not locate a resource for Addressing." + strResourceName);
if (property.PropertyType != typeof(string))
throw new InvalidOperationException("The requested resource does not return a string.");
return (string) property.GetValue(null, null);
}
Then in my Spark view, I can use:
<li id="city" if="Model.IsCityVisible">
<label for="City">${Model.GetLabel("City")}</label>
${Html.EditorFor(x => x.City)}
!{Html.ValidationMessage("City", Model.GetValidationMessage("City"))}
</li>
精彩评论