CodingYourLife

CodingYourLife

 

Referenzen

 
 

MVC server-/clientseitige Validierung mehrsprachig

In diesem Tutorial erfährt ihr wie ihr in MVC den Datepicker sowie die Eingabe von Zahlen mit Punkt und Komma mehrsprachig validieren könnt. Beim Datepicker ist sowohl der Text, als auch die Ländereinstellung sprachspezifisch.

Vorbereitung, Pakete downloaden/installieren
Als erstes benötigen wir die NuGet Pakete (eventuell sind die js Files unterhalb auch als NuGet Pakete verfügbar). Mit Rechtsklick auf das Projekt NuGet Pakete verwalten und klickt dann auf Online und wählt Rechts oben die Suche aus.
Dann sucht man nach MvcHtml5 Templates und installiert dieses Paket, das unter anderem das DateTime.cs EditorTemplate isntalliert und den inputs von DateTime Feldern ein >>type=“datetime“<< oder >>type=“date“<< verpasst. Des weiteren holen wir uns über die Suche „jquery-ui-i18n„.

Die benötigten js Files
jquery.global.js
jquery.glob.all.js

Language Dropdown
Html Code für *.cshtml File (z.B. _Layout.cshtml):

@using (Html.BeginForm("ChangeCulture", "Language", FormMethod.Post, new { @id = "langForm" }))
{
	
	
}

Der Language Controller

public class LanguageController : Controller
{
	[HttpPost]
	public ActionResult ChangeCulture(string language, string returnUrl)
	{
		if (language != string.Empty)
		{
			CultureInfo culture = new CultureInfo(language);
			Thread.CurrentThread.CurrentCulture = culture;
			Thread.CurrentThread.CurrentUICulture = culture;

			var langCookie = new HttpCookie("lang", language)
			{
				HttpOnly = true
			};

			Response.AppendCookie(langCookie);
		}

			return this.Redirect(returnUrl);
	}
}

In global.asax:

protected void Application_AcquireRequestState(object sender, EventArgs e)
{
	var langCookie = HttpContext.Current.Request.Cookies["lang"];
	if (langCookie != null)
	{
		var ci = new CultureInfo(langCookie.Value);

		// Setting culture for each request
		Thread.CurrentThread.CurrentUICulture = ci;
		Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
	}
}

jqueryval in BundleConfig.cs auskommentieren (um es manuell einzubinden)
Ich bin kein Freund der Bundle.Config.cs. Vielleicht übersehe ich da etwas ganz schlaues aber meiner Erfahrung nach macht diese während der Entwicklung nur undurchsichtige Probleme. So kam es mir auch diesmal vor mit jqueryval. Also besser erst mal jqueryval auskommentieren.

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
	//"~/Scripts/jquery.validate*",
	//"~/Scripts/jquery.unobtrusive*"
));

Meta Extension Method der aktuellen Sprache
Nachdem die ausgewählt Sprache nicht so einfach in Javascript herauszufinden ist, gibt es die Möglichkeit ein Meta Tag zu setzen.

namespace System.Web.Mvc
{
    public static class LocalizationHelpers
    {
        public static IHtmlString MetaAcceptLanguage(this HtmlHelper html)
        {
            var acceptLanguage = HttpUtility.HtmlAttributeEncode(Threading.Thread.CurrentThread.CurrentUICulture.ToString());
            return new HtmlString(string.Format("", acceptLanguage));
        }
    }
}

Mein Header inkludiert die folgenden wichtigen Files

@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryui")


@Html.MetaAcceptLanguage()






Fixes und Datepicker mit jeweiliger Spracheinstellung
Jetzt werden noch diverse fixes angewendet und der Datepicker angewendet (im Header gleich darunter).


Das sollte es clientseitig auch schon gewesen sein. Könnte einfacher sein...

Custom Model Bindings für Decimal und DateTime
In global.asax

protected void Application_Start()
{
	//custom model bindings for localization
	ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
	ModelBinders.Binders.Add(typeof(DateTime), new DateTimeModelBinder());
	ModelBinders.Binders.Add(typeof(DateTime?), new DateTimeModelBinder());
}

Der Decimal Model Binder

public class DecimalModelBinder : IModelBinder
{
	public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
	{
		ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
		ModelState modelState = new ModelState { Value = valueResult };
		object actualValue = null;
		try
		{
			actualValue = Convert.ToDecimal(valueResult.AttemptedValue, CultureInfo.CurrentCulture);
		}
		catch (FormatException e)
		{
			modelState.Errors.Add(e);
		}

		bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
		return actualValue;
	}
}

The DateTime Model Binder

	public class DateTimeModelBinder : IModelBinder
	{
		public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
		{
			var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
			var date = value.ConvertTo(typeof(DateTime), CultureInfo.CurrentCulture);

			return date;
		}
	}

Speziellen Dank an Scott Hanselman für seinen Blogeintrag dazu. Weiter in die Tiefe können interessierte hier gehen jquery-global. Ein jqueryui Timepicker Addon ist nur ein klein bisschen mehr Arbeit. Meine Lösung ist aus diversen Quellen zusammengetragen und mit viel rumprobieren entstanden xD. Kommentare sind willkommen!

Kommentar schreiben

Kommentar

Hallo
Toller Artikel. Für mich wäre es noch interessant zu sehen wie das ganze funktioniert, wenn eine Kommazahl in einem ViewModel mit anderen Datentypen zusammen enthalten ist. Insbesondere wie die Action Methode des Controllers aussieht.

Adrian