Modificare l’impostazione di formato DateTime analisi ASP.NET Core

Ho una Data in un ASP.NET Core Controller come questo:

public class MyController:Controller{
    public IActionResult Test(DateTime date) {

    }
}

Il quadro è in grado di analizzare la data, ma solo in formato inglese. Quando passo 04.12.2017 come parametro di data, voglio dire, il 4 dicembre 2017. Questo potrebbe ottenere analizzato come l’inglese, quindi la mia data oggetto si ottiene il valore 12 aprile 2017. Ho cercato di aggiungere solo in tedesco utilizzando questo articolo e anche questo, ma senza successo.

Ciò che deve essere fatto ASP.NET Core analizzare automaticamente le date è corretta tedesco formato?

Aggiornamento
Ho Provato a impostare la RequestLocalizationOptions

services.Configure<RequestLocalizationOptions>(opts =>
{
    var supportedCultures = new[]
    {
        new CultureInfo("de-DE"),
    };

    opts.DefaultRequestCulture = new RequestCulture("de-DE");
    //Formatting numbers, dates, etc.
    opts.SupportedCultures = supportedCultures;
    //UI strings that we have localized.
    opts.SupportedUICultures = supportedCultures;
});

Ancora non funziona. Io chiamo example.com/Test?date=12.04.2017 e ottenuto questo nella mia debugger:

public IActionResult Test(DateTime date) {
    string dateString = date.ToString("d"); //04.12.2016
    string currentDateString = DateTime.Now.ToString("d"); //14.01.2016
    return Ok();
}
Come stai passando le date per essere analizzati, mostrano il formato dell’URL che fare.
Come ho detto: Una chiamata con il Test?data=12.04.2017 parametro risultati in 04.12.2017 come la data e l’oggetto all’interno della funzione di Test. Mi aspetto originale data, in modo 12.04.2017 invece di 04.12.2017.
Passare come una stringa, quindi utilizzare DateTime.ParseExact di analizzarlo esattamente in che modo si desidera.
Per un punto di chiarezza (per aiutare la discussione) 04.12.2017 essere 4 dicembre inglese formato, o più precisamente l’inglese britannico. Essendo 12 aprile è inglese formato. Anche se il regno UNITO sarebbe utilizzare un / invece di una . come separatore.
ciao @Lion ho incollato Avvio.cs per asp.net core tipo di progetto e impostare la cultura info . quando ho guardato cultura nel mio controller è stato impostato per DE . Si prega di provare questo, se questo aiuta . L’ho provato, mi ha mostrato le date nel formato DE . Non ho provato con il parametro controller po ‘ om finestra Immediata .

OriginaleL’autore Lion | 2017-01-13

9 Replies
  1. 7

    Avuto lo stesso problema. Passando DateTime nella richiesta del corpo funziona bene (perché Json converter gestisce questo personale), passando DateTime nella stringa di query come parametro ha un po ‘ di cultura questioni.

    Non mi piace il “cambiare tutte le richieste di cultura” approccio, perché questo potrebbe avere un impatto su un altro tipo di analisi, che non è desiderabile.

    Quindi la mia scelta è stata per ignorare l’impostazione predefinita DateTime modello di associazione utilizzando IModelBinder: https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding

    Quello che ho fatto:

    1) Definire personalizzato legante (c# 7 la sintassi per il ‘fuori’ il parametro è utilizzato):

    public class DateTimeModelBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
                throw new ArgumentNullException(nameof(bindingContext));
    
            //Try to fetch the value of the argument by name
            var modelName = bindingContext.ModelName;
            var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
            if (valueProviderResult == ValueProviderResult.None)
                return Task.CompletedTask;
    
            bindingContext.ModelState.SetModelValue(modelName, valueProviderResult);
    
            var dateStr = valueProviderResult.FirstValue;
            //Here you define your custom parsing logic, i.e. using "de-DE" culture
            if (!DateTime.TryParse(dateStr, new CultureInfo("de-DE"), DateTimeStyles.None, out DateTime date))
            {
                bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, "DateTime should be in format 'dd.MM.yyyy HH:mm:ss'");
                return Task.CompletedTask;
            }
    
            bindingContext.Result = ModelBindingResult.Success(date);
            return Task.CompletedTask;
        }
    }

    2) Definire il fornitore per il vostro raccoglitore:

     public class DateTimeModelBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
    
            if (context.Metadata.ModelType == typeof(DateTime) || 
                context.Metadata.ModelType == typeof(DateTime?))
            {
                return new DateTimeModelBinder();
            }
    
            return null;
        }
    }

    3) E, infine, registra il tuo provider per essere utilizzato da ASP.NET Core:

    services.AddMvc(options =>
    {
        options.ModelBinderProviders.Insert(0, new DateTimeModelBinderProvider());
    });

    Ora il tuo DateTime verrà analizzato come previsto.

    Ha lavorato come un fascino. Grazie!
    la Documentazione Microsoft suggerisce di non utilizzo di leganti modello Personalizzato per la conversione di stringhe di altri tipi, come best practice: in Genere non dovrebbe essere utilizzato per convertire una stringa in un tipo personalizzato, un TypeConverter è di solito una scelta migliore.. Considerare l’utilizzo di TypeConverter
    Grazie, ha funzionato anche per me. Solo una nota: il modello del raccoglitore di cui sopra non gestisce bene DateTime? i valori null.

    OriginaleL’autore Igor Fedchenko

  2. 5

    Volevo formattare le date nelle mie risposte e ho fatto la seguente in ConfigureServices metodo:

    services.AddMvc()
    .AddJsonOptions(options =>
    {
        options.SerializerSettings.DateFormatString = "mm/dd/yy, dddd";
    });

    Speranza che aiuta.

    Grazie. Se si desidera utilizzare solo per un caso particolare può essere specificato quando la conversione pure var deserialized = JsonConvert.DeserializeObject(myJsonstring, new JsonSerializerSettings { DateFormatString = "dd/MM/yyyy" });

    OriginaleL’autore PayamGerami

  3. 1

    MVC ha sempre usato InvariantCulture per instradare i dati e le stringhe di query (parametri che vanno nell’URL). Il motivo è che gli Url in applicazione localizzata deve essere universale. In caso contrario, un url in grado di fornire dati diversi a seconda della localizzazione dell’utente.

    È possibile sostituire la query e percorso ValueProviderFactories con la tua che rispetto la cultura corrente (o utilizzare method="POST" in moduli)

    public class CustomValueProviderFactory : IValueProviderFactory
    {
        public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
    
            var query = context.ActionContext.HttpContext.Request.Query;
            if (query != null && query.Count > 0)
            {
                var valueProvider = new QueryStringValueProvider(
                    BindingSource.Query,
                    query,
                    CultureInfo.CurrentCulture);
    
                context.ValueProviders.Add(valueProvider);
            }
    
            return Task.CompletedTask;
        }
    }
    
    services.AddMvc(opts => {
        //2 - Index QueryStringValueProviderFactory
        opts.ValueProviderFactories[2] = new CustomValueProviderFactory(); 
    })

    P. S. è un comportamento ragionevole, ma non capisco perché la documentazione non coprire questa cosa molto importante.

    OriginaleL’autore justserega

  4. 0
                  using System;
            using System.Collections.Generic;
            using System.Linq;
            using System.Threading.Tasks;
            using Microsoft.AspNetCore.Builder;
            using Microsoft.AspNetCore.Hosting;
            using Microsoft.Extensions.Configuration;
            using Microsoft.Extensions.DependencyInjection;
            using Microsoft.Extensions.Logging;
            using Microsoft.Extensions.Options;
            using System.Globalization;
            using Microsoft.AspNetCore.Localization;
    
            namespace coreweb
            {
                public class Startup
                {
                    public Startup(IHostingEnvironment env)
                    {
                        var builder = new ConfigurationBuilder()
                            .SetBasePath(env.ContentRootPath)
                            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                            .AddEnvironmentVariables();
    
                        if (env.IsDevelopment())
                        {
                            //This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
                            builder.AddApplicationInsightsSettings(developerMode: true);
                        }
                        Configuration = builder.Build();
                    }
    
                    public IConfigurationRoot Configuration { get; }
    
                    //This method gets called by the runtime. Use this method to add services to the container.
                    public void ConfigureServices(IServiceCollection services)
                    {
                        //... previous configuration not shown
                        services.AddMvc();
                        services.Configure<RequestLocalizationOptions>(
                            opts =>
                            {
                                var supportedCultures = new[]
                                {
    
                            new CultureInfo("de-DE"),
                                };
    
                                opts.DefaultRequestCulture = new RequestCulture("de-DE");
                        //Formatting numbers, dates, etc.
                        opts.SupportedCultures = supportedCultures;
                        //UI strings that we have localized.
                        opts.SupportedUICultures = supportedCultures;
                            });
                    }
    
                    //This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
                    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
                    {
                        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
                        loggerFactory.AddDebug();
    
                     //  app.UseApplicationInsightsRequestTelemetry();
    
                        if (env.IsDevelopment())
                        {
                            app.UseDeveloperExceptionPage();
                            app.UseBrowserLink();
                        }
                        else
                        {
                            app.UseExceptionHandler("/Home/Error");
                        }
    
                      // app.UseApplicationInsightsExceptionTelemetry();
    
                        app.UseStaticFiles();
    
                        var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
                        app.UseRequestLocalization(options.Value);
    
    
    
                        app.UseMvc(routes =>
                        {
                            routes.MapRoute(
                                name: "default",
                                template: "{controller=Home}/{action=Index}/{id?}");
                        });
                    }
                }
            }
    Non funziona. Viene applicato a DateTime.Now ma non è l’argomento che ha analizzato il parametro. Si prega di vedere la mia modifica in questione causa della sua troppo lungo per un commento.
    ohhh . fammi controllare con la vostra modifica di risposta . solo per confermare quello che dovrebbe essere il risultato corretto in questo caso ?
    12.04.2017 come input deve essere analizzato come 12 aprile 2014, invece, 4 dicembre 2014 come ASP.NET fa.

    OriginaleL’autore Yashveer Singh

  5. 0

    Se non ti dispiace utilizzando il generico StatusCode metodo per effettuare questa chiamata, si può fare qualcosa di simile:

    internal IActionResult CreateResponse(int code, object content = null)
        {
            Type t = content?.GetType();
            bool textContent = t == typeof(string) || t == typeof(bool);
            //
            JsonSerializerSettings dateFormatSettings = new JsonSerializerSettings
            {
    
                DateFormatString = myDateFormat
            };
    
            string bodyContent = content == null || string.IsNullOrWhiteSpace(content + "")
                        ? null
                        : textContent
                            ? content + ""
                            : JsonConvert.SerializeObject(content, dateFormatSettings);
    
            ObjectResult or = base.StatusCode(code, bodyContent);
            string mediaType = 
                        !textContent
                            ? "application/json"
                            : "text/plain";
            or.ContentTypes.Add(new MediaTypeHeaderValue(mediaType));
            return or;
        }

    Si può aggiungere a una classe di base e di chiamare le cose come:

    return base.CreateResponse(StatusCodes.Status200OK, new { name = "My Name", age = 23});

    Spetta a voi se si desidera creare il proprio Ok, BadRequest, ecc…metodi, ma per me questo funziona e spero che aiuta chiunque altro. Si potrebbe anche di default int codice = 200, se la maggior parte delle richieste Arriva. Questo codice si presuppone che si desidera rispondere con una stringa, booleano, o un oggetto personalizzato, ma si può facilmente gestire tutte le primitive controllando Tipo.GetTypeInfo().IsPrimitive e anche di fare alcuni controlli per il decimale, stringa, data e ora, Durata, DateTimeOffset o Guid.

    OriginaleL’autore pqsk

  6. 0

    Ho avuto lo stesso problema ad quasi impazzita. Ho provato di tutto senza sucsses. Prima ho trovato una soluzione alternativa per risolvere il mio problema:

    Soluzione:

    string data1 
    string horainicio 
    string horafim
    
    var ageData = new AgendaData();
    var user = await _userManager.GetUserAsync(User);
    string usuario = user.Id;
    int empresa = user.IdEmpresa;
    int Idprospect = Convert.ToInt32(prospect);
    int minutos = 0;           
    var tipoAgenda = TipoAgenda.Contato;
    
    var provider = CultureInfo.InvariantCulture;
    provider = new CultureInfo("en-US");            
    string formato = "dd/MM/yyyy HH:mm";
    
    var dataInicio = DateTime.ParseExact(data1 + " " + horainicio, formato, provider);
    var dataFim = DateTime.ParseExact(data1 + " " + horafim, formato, provider);           
    var dataAlerta = dataInicio.AddMinutes(-minutos);

    Ma, in questo modo ho sempre necessario impostare invariantculture a tutti i miei datetime. Ho trovato la soluzione impostazione della mia cultura presso la configurazione di avvio.cs.

    Set di Cultura all’avvio.cs

     public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, CRMContext context)
            {
                loggerFactory.AddConsole(Configuration.GetSection("Logging"));
                loggerFactory.AddDebug();
    
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                    app.UseDatabaseErrorPage();
                    app.UseBrowserLink();
                }
                else
                {
                    app.UseExceptionHandler("/Home/Error");
                }
    
                //Fixar Cultura para en-US
                RequestLocalizationOptions localizationOptions = new RequestLocalizationOptions
                {
                    SupportedCultures = new List<CultureInfo> { new CultureInfo("en-US") },
                    SupportedUICultures = new List<CultureInfo> { new CultureInfo("en-US") },
                    DefaultRequestCulture = new RequestCulture("en-US")
                };
    
                app.UseRequestLocalization(localizationOptions);      
                app.UseStaticFiles();
                app.UseIdentity();
    
                //Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715
    
                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}");
                });
    
                context.Database.EnsureCreated();
            }

    Spero che questo vi aiuterà.

    OriginaleL’autore Rogerio Azevedo

  7. 0

    Considerare l’utilizzo di un custom TypeConverter per il tuo datetime (Fonte):

    using System;
    using System.ComponentModel;
    using System.Globalization;
    using System.Drawing;
    
    public class DeDateTimeConverter : TypeConverter {
       //Overrides the CanConvertFrom method of TypeConverter.
       //The ITypeDescriptorContext interface provides the context for the
       //conversion. Typically, this interface is used at design time to 
       //provide information about the design-time container.
       public override bool CanConvertFrom(ITypeDescriptorContext context, 
          Type sourceType) {
    
          if (sourceType == typeof(string)) {
             return true;
          }
          return base.CanConvertFrom(context, sourceType);
       }
       //Overrides the ConvertFrom method of TypeConverter.
       public override object ConvertFrom(ITypeDescriptorContext context, 
          CultureInfo culture, object value) {
          if (value is string) {
             if (DateTime.TryParse(((string)value), new CultureInfo("de-DE") /*or use culture*/, DateTimeStyles.None, out DateTime date))
                 return date;
          }
          return base.ConvertFrom(context, culture, value);
       }
    }

    e utilizzare TypeConverter attributo proprietà:

    [TypeConverter(typeof(DeDateTimeConverter))]
    public DateTime CustomDateTime { get; set; }

    Aggiornamento

    Sulla base della mia esperienza e grazie a questa risposta e @zdeněk commento, TypeConverter attributo non funzionano e si dovrebbe registrare TypeConverter in Startup.cs:

    TypeDescriptor.AddAttributes(typeof(DateTime), new TypeConverterAttribute(typeof(DeDateTimeConverter)));

    OriginaleL’autore KiNG

  8. -1

    Provare a impostare la cultura manualmente nel vostro web.config

    <configuration>
       <system.web>    
          <globalization culture="de-DE" uiCulture="de-DE"/>
       </system.web>
    </configuration>

    EDIT: Dal momento che ho capito che questo è il Nucleo, è possibile farlo in questo modo all’Avvio.Configurare:

    var cultureInfo = new CultureInfo("de-DE");
    CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
    CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
    La domanda era Asp.NET Core
    Ho già provato impostazione CultureInfo.DefaultThreadCurrentCulture e CultureInfo.DefaultThreadCurrentUICulture e all’inizio del Test d’azione, sono correttamente impostato su DE. Ma ASP.NET core non cura, il parametro viene analizzato sbagliato.

    OriginaleL’autore maksymiuk

  9. -3
    DateTime dt = DateTime.ParseExact(dateString, "ddMMyyyy", CultureInfo.InvariantCulture);
    dt.ToString("yyyyMMdd");

    Come per https://stackoverflow.com/a/3477821/2914174

    So che questo. Ma non aiuta qui causa ASP.NET Nucleo stesso di analizzare il parametro GET a un oggetto DateTime. Non faccio l’analisi. Sarebbe una soluzione di usare una stringa invece di DateTime data argomento e quindi analizzare come tu suggerisci. Ma voglio evitare questa causa ASP.NET Core di fare un buon lavoro qui, solo con il formato sbagliato.
    hai provato la mia risposta ?

    OriginaleL’autore Ryan

Lascia un commento