c# tesi - Qual è il modo migliore per gestire la convalida con culture diverse





laurea igiene (3)


Ci sono 2 plugin jQuery Globalize.

La vecchia versione è v0.0.1 contiene uno script globalize.js e ha una sottocartella di cultures cui puoi trovare tutte le culture di script come:

  • globalize.culture.en-AU.js
  • globalize.culture.es-AR.js

questi script ti consentono di aggiungere il maggior numero di culture che vuoi, quindi sarebbe perfetto per il tuo bundle costruito in questo modo:

bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
    "~/Scripts/globalize.js",
    "~/Scripts/cultures/globalize.culture.en-AU.js",
    "~/Scripts/cultures/globalize.culture.es-AR.js"
));

Globalize avrà una raccolta di script di localizzazione che puoi impostare semplicemente usando:

Globalize.culture('en-AU');

o

Globalize.culture('es-AR');

Può utilizzare una sorta di prossimità per capire quale sia la cultura più vicina che si desidera utilizzare. Se hai caricato nel tuo pacchetto globalize.culture.es-AR.js puoi impostare Globalize.culture('es'); e Globalize sarebbe in grado di capire che si desidera utilizzare la cultura 'es-AR'; ovviamente se hai aggiunto globalize.culture.es.js il loader avrebbe scelto quest'ultimo.

La nuova versione di jQuery Globalize (stabile) è v1.0.0 e funziona in un modo completamente diverso.

Ha ancora il file di script principale chiamato globalize.js ma devi aggiungere molti più script per farlo funzionare.

Qualcuno ha creato uno tool che ti dice esattamente quale script hai bisogno, a seconda del tipo di modulo (numero, date, valute) che vuoi usare.

Se si sta optando per utilizzare v1.0.0, si vedrà che lo strumento suggerirà di includere gli script di base (solo numeri):

  • cldr.js
  • CLDR / event.js
  • CLDR / supplemental.js
  • globalize.js
  • globalizzare / number.js

più alcuni script CLSON JSON:

  • CLDR / supplementare / likelySubtags.json
  • CLDR / main / {locale} /numbers.json
  • CLDR / supplementare / numberingSystems.json

Puoi trovare questi file nel pacchetto core e nel pacchetto dei numbers .
Se vuoi convalidare le date questo è il package . Maggiori informazioni here .

Questi sono tutti file json e non è possibile raggrupparli. Puoi caricarli in fase di esecuzione facendo qualcosa del genere:

Application.loadCulture = function (culture) {

    $.when(
      $.get(Application.CldrFetch + '/' + culture + '/' + encodeURIComponent("likelySubtags.json")),
      $.get(Application.CldrFetch + '/' + culture + '/' + "numberingSystems.json"),
      $.get(Application.CldrFetch + '/' + culture + '/' + "plurals.json"),
      $.get(Application.CldrFetch + '/' + culture + '/' + "ordinals.json"),
      $.get(Application.CldrFetch + '/' + culture + '/' + "currencyData.json"),
      $.get(Application.CldrFetch + '/' + culture + '/' + "timeData.json"),
      $.get(Application.CldrFetch + '/' + culture + '/' + "weekData.json"),
      $.get(Application.CldrFetch + '/' + culture + '/' + "ca-gregorian.json"),
      $.get(Application.CldrFetch + '/' + culture + '/' + "timeZoneNames.json"),
      $.get(Application.CldrFetch + '/' + culture + '/' + "numbers.json"),
      $.get(Application.CldrFetch + '/' + culture + '/' + "currencies.json")
    )
    .then(function () {
        // Normalize $.get results, we only need the JSON, not the request statuses.
        return [].slice.apply(arguments, [0]).map(function (result) {
            return result[0];
        });

    }).then(Globalize.load).then(function () {
        Globalize.locale(culture);
    });
};

Comunque; diciamo che vuoi restare fedele alla vecchia v0.0.1 che è ancora la migliore.
Il tuo bundle avrà lo script globalize e quelli culturali:

bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
    "~/Scripts/globalize.js",
    "~/Scripts/cultures/globalize.culture.en-AU.js",
    "~/Scripts/cultures/globalize.culture.es-AR.js"
));

La convalida di jQuery offre qualche altra estensione aggiuntiva che potresti voler considerare:

  • ulteriore-methods.js
  • localization / messages_es_AR.js (messaggi di errore per la cultura)

Ho visto che stai impostando la tua cultura in Application_AcquireRequestState . Qualcuno suggerisce che è meglio farlo in Application_BeginRequest mentre viene elaborato in precedenza nella pipe:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
        string cultureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
        CultureInfo ci = new CultureInfo(cultureCode);
        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureCode);
        System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
    }

Sembra che tu stia usando questo plugin jQuery per la convalida. Quello che normalmente farei è, non appena carico lo script, configurare la cultura e impostare la convalida personalizzata:

    Globalize.culture(this.culture);

    $.validator.methods.number = function (value, element) {
        return this.optional(element) || jQuery.isNumeric(Globalize.parseFloat(value));
    };

    $.validator.methods.date = function (value, element) {
        return (this.optional(element) || Globalize.parseDate(value));
    };

    jQuery.extend(jQuery.validator.methods, {
        range: function (value, element, param) {
            var val = Globalize.parseFloat(value);
            return this.optional(element) || (val >= param[0] && val <= param[1]);
        }
    });

Una cosa che ti manca è un raccoglitore di modelli per decimali:

using System;
using System.Web.Mvc;
using System.Globalization;

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
        {
            //Check if this is a nullable decimal and a null or empty string has been passed
            var isNullableAndNull = (bindingContext.ModelMetadata.IsNullableValueType && string.IsNullOrEmpty(valueResult.AttemptedValue));

            //If not nullable and null then we should try and parse the decimal
            if (!isNullableAndNull)
            {
                actualValue = decimal.Parse(valueResult.AttemptedValue, NumberStyles.Any, CultureInfo.CurrentCulture);
            }
        }
        catch (FormatException e)
        {
            modelState.Errors.Add(e);
        }

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

che può essere impostato in Global.asax Application_Start :

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());

Questo è praticamente tutto ciò di cui hai bisogno.

C'è solo un fastidioso problema con questo approccio.
Diciamo che stai usando la cultura en-AU e inserisci nel tuo campo numerico un valore: 10,4. Questo numero è perfettamente valido in es-AR ma dovrebbe essere non valido per la cultura en-AU .

jQuery Globalize lo considererà comunque valido poiché lo traslare in 104 qui:

$.validator.methods.number = function (value, element) {
    return this.optional(element) || jQuery.isNumeric(Globalize.parseFloat(value));
};

Globalize.parseFloat('10,4') per la cultura en-AU trasformerebbe quel numero in 104.

Stessa cosa succederebbe se si facesse lo stesso per Globalize.parseFloat('10.4') per la cultura es-AR; sarebbe, di nuovo, 104.

Puoi controllare questo comportamento eseguendo questo fiddle .

Entrambi e . sono simboli validi come sarebbero usati come separatore decimale e separatore di migliaia.

Ci sono alcuni problemi aperti su questo argomento su github e immagino che sarebbe difficile da sistemare visto che ora stanno lavorando sulla nuova versione, a proposito del quale persiste lo stesso problema.

Stai affrontando lo stesso problema sul lato server con il nostro modello di decimale :

decimal.Parse('10,4', NumberStyles.Any, CultureInfo.CurrentCulture);

dove CultureInfo.CurrentCulture è "en-AU", produrrebbe di nuovo lo stesso risultato: 104 .

Può posizionare un punto di interruzione e vedere come converte il valore.

Immagino che probabilmente sarebbe più facile da risolvere, magari usando alcune espressioni regolari.

Se vuoi giocare con la soluzione con jQuery Validator v.0.1.1 o jQuery Validator v.1.0.0 ho creato due repository here e here .

Sto cercando di creare un'applicazione MVC multilingue. Ho un modulo nella mia domanda e ho campo per inserire un costo. Sono in grado di creare un disco usando la cultura spagnola.

Ma cercando di aggiornare il record, sto ricevendo la convalida di jquery falsa. e ricevo un messaggio di errore predefinito come:

Il campo deve essere numerico.

Nel mio modello di vista ho impostato i seguenti attributi.

[LocalizedDisplayName("Label_Cost")]
[RegularExpression("^[^<>,<|>]+$", ErrorMessage = null, ErrorMessageResourceName = "Error_Message_Html_Tags_Prevented", ErrorMessageResourceType = typeof(Resources))]
[Range(0, 9999.99, ErrorMessage = null, ErrorMessageResourceName = "Error_Message_Cost_Not_Valid", ErrorMessageResourceType = typeof(Resources))]
public decimal? Cost { get; set; }

Ho impostato il mio file Gobal.asax con il seguente

protected void Application_AcquireRequestState(object sender, EventArgs e)
{
    try
    {
        HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
        string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
        CultureInfo ci = new CultureInfo(culutureCode);
        System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
        System.Threading.Thread.CurrentThread.CurrentCulture =
        CultureInfo.CreateSpecificCulture(ci.Name);
    }
    catch(Exception ex)
    {
        // Code
    }
}

e il metodo sopra funziona come previsto sul lato server nel cambiare la cultura. Ma la convalida del lato client si interrompe sulle culture non inglesi poiché javascript riconosce solo i letterali decimali. Mi piacerebbe conoscere il modo migliore per estendere la convalida del lato client mvc con la convalida specifica della cultura.

MODIFICARE

Con riferimento all'URL di Mike, ho apportato le seguenti modifiche al pacchetto Js. Il pacchetto Js è il seguente

public static void RegisterBundles(BundleCollection bundles)
{
   BundleTable.EnableOptimizations = true;

  bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
               "~/Scripts/globalize.js",
               "~/Scripts/globalize/currency.js",
                "~/Scripts/globalize/date.js",
                "~/Scripts/globalize/message.js",
                "~/Scripts/globalize/number.js",
                "~/Scripts/globalize/plural.js",
                "~/Scripts/globalize/relative-time.js"));

  bundles.Add(new ScriptBundle("~/bundles/globalisationEN").Include(
               "~/Scripts/GlobalisationCulture/globalize.culture.en-AU.js"));

            bundles.Add(new ScriptBundle("~/bundles/globalisationES").Include(
               "~/Scripts/GlobalisationCulture/globalize.culture.es-AR.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryuiEN").Include(
                        "~/Scripts/jquery-ui-1.10.3.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryuiES").Include(
                        "~/Scripts/jquery-ui-1.10.3.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                "~/Scripts/jquery.validate.js",
                "~/Scripts/jquery.validate.unobtrusive.js",
                "~/Scripts/jquery.unobtrusive-ajax.js",
                "~/Scripts/jquery.validate.globalize.js"));
}

Nella pagina di layout ho implementato come segue

HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
        string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
        if (culutureCode.Equals("en-AU", StringComparison.OrdinalIgnoreCase))
        {
            culutureCode = "EN";
        }
        else if (culutureCode.Equals("es-AR", StringComparison.OrdinalIgnoreCase))
        {
            culutureCode = "ES";
        }
        else
        {
            culutureCode = "EN";
        }
@Scripts.Render("~/bundles/jquery",
                    "~/bundles/globalisation",
                    string.Format("~/bundles/globalisation{0}", culutureCode),
                    "~/bundles/jqueryval",
                    string.Format("~/bundles/jqueryui{0}", culutureCode))



Hai aggiunto pacchetti in RegisterBundles ma non li hai utilizzati nella pagina di layout. Hai anche aggiunto il file jqueryui ridondante in RegisterBundles. Aggiorna il tuo metodo RegisterBundles in questo modo:

public static void RegisterBundles(BundleCollection bundles)
 {
   BundleTable.EnableOptimizations = true;
   bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                    "~/Scripts/jquery-{version}.js"));
   bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
            "~/Scripts/globalize.js",                
            "~/Scripts/globalize/currency.js",
            "~/Scripts/globalize/date.js",
            "~/Scripts/globalize/message.js",
            "~/Scripts/globalize/number.js",
            "~/Scripts/globalize/plural.js",
            "~/Scripts/globalize/relative-time.js"));
   bundles.Add(new ScriptBundle("~/bundles/globalisationEN").Include(
           "~/Scripts/GlobalisationCulture/globalize.culture.en-AU.js"));
   bundles.Add(new ScriptBundle("~/bundles/globalisationES").Include(
           "~/Scripts/GlobalisationCulture/globalize.culture.es-AR.js"));
   bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
                    "~/Scripts/jquery-ui-1.10.3.js"));      

   bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
            "~/Scripts/jquery.validate.js",
            "~/Scripts/jquery.validate.unobtrusive.js",
            "~/Scripts/jquery.unobtrusive-ajax.js",
            "~/Scripts/jquery.validate.globalize.js"));
  }

e quindi aggiornare la pagina di layout in questo modo:

@section Scripts 
{
    @Scripts.Render("~/bundles/jquery",
                "~/bundles/globalisation",
                "~/bundles/globalisationEN",
                "~/bundles/globalisationES",
                "~/bundles/jqueryval",
                "~/bundles/jqueryui"))

   <script type="text/javascript">
    $.validator.methods.number = function (value, element) {
        return this.optional(element) ||
            !isNaN(Globalize.parseFloat(value));
    }
    $(document).ready(function () {
        Globalize.culture('es-AR'); //set spanish culture
    });

   </script>
}

Spero che questo aiuterà :)




Uno dei membri del team nel nostro ufficio ha fornito le seguenti indicazioni su quando utilizzare const, static e readonly:

  • Usa const quando hai una variabile di un tipo che puoi conoscere al runtime (string letteral, int, double, enum, ...) che vuoi che tutte le istanze o i consumatori di una classe abbiano accesso a dove il valore non dovrebbe cambiare.
  • Usa statico quando hai dati che vuoi che tutte le istanze o i consumatori di una classe abbiano accesso a dove il valore può cambiare.
  • Usa statico readonly quando hai una variabile di un tipo che non puoi sapere in runtime (oggetti) a cui vuoi che tutte le istanze o i consumatori di una classe abbiano accesso dove il valore non dovrebbe cambiare.
  • Usa readonly quando hai una variabile a livello di istanza che saprai al momento della creazione dell'oggetto che non dovrebbe cambiare.

Un'ultima nota: un campo const è statico, ma l'inverso non è vero.







c# asp.net-mvc validation asp.net-mvc-4 globalization