2017-01-13 4 views
4

я получаю дату в качестве ядра контроллера ASP.NET так:Изменить формат по умолчанию для DateTime разборе в ASP.NET Ядра

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

    } 
} 

Каркас может разобрать дату, но только на английском формате. Когда я передаю 04.12.2017 как параметр даты, я имею в виду 4 декабря 2017 года. Это получило бы синтаксический анализ как английская дата, поэтому мой объект даты получит значение 12 апреля 2017 года. Я попробовал добавить немецкий только с помощью статьи this, а также this, но безуспешно.

Что необходимо сделать, чтобы ASP.NET Core автоматически обрабатывал даты в правильном формате в Германии?

Update Я попытался установить 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; 
         }); 

еще не работает. Я называю example.com/Test?date=12.04.2017 и получил это в моем отладчика:

public IActionResult Test(DateTime date) { 
    string dateString = date.ToString("d"); // 04.12.2016 
    string currentDateString = DateTime.Now.ToString("d"); // 14.01.2016 
    return Ok(); 
} 
+0

Как вы проходите время, которое нужно разобрать, покажите формат URL-адреса, который вы делаете. –

+0

@ScottChamberlain Как я уже сказал: параметр call with test? Date = 12.04.2017 приводит к * 04.12.2017 * в качестве объекта даты внутри функции Test. Я ожидаю немодифицированную дату, поэтому 12.04.2017 вместо 04.12.2017. – Lion

+0

Передайте его как строку, затем используйте 'DateTime.ParseExact', чтобы разобрать его точно так, как вы хотите. –

ответ

-1

Попробуйте установить культуру вручную в вашем web.config

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

EDIT: Так как я только что понял, это ядро, вы можете сделать это таким образом в StartUp.Configure:

var cultureInfo = new CultureInfo("de-DE"); 
CultureInfo.DefaultThreadCurrentCulture = cultureInfo; 
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo; 
+3

Вопрос был о Asp.NET Core – Pawel

+0

Я уже пробовал настройку 'CultureInfo.DefaultThreadCurrentCulture' и' CultureInfo.DefaultThreadCurrentUICulture' и в начале тестового действия они правильно настроены на ** де-DE **. Но ядро ​​ASP.NET не волнует, параметр GET анализируется неправильно. – Lion

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

По https://stackoverflow.com/a/3477821/2914174

+2

Я знаю это. Но здесь не помогает заставить сам ASP.NET Core анализировать параметр GET для объекта DateTime. Я не разбираюсь.Было бы обходным путем использовать строку вместо DateTime в качестве аргумента date, а затем проанализировать ее, как вы предлагаете. Но я хочу избежать этой причины, чтобы ASP.NET Core делал здесь хорошую работу, только с неправильным форматом. – Lion

+0

@ Lion вы попробовали мой ответ? –

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?}"); 
        }); 
       } 
      } 
     } 
+0

Не работает. Применяется к 'DateTime.Now', но не аргумент, который получил синтаксический анализ из параметра GET. Пожалуйста, см. Мое редактирование в вопросе, потому что слишком долго для комментария. – Lion

+0

ohhh. позвольте мне проверить ваш отредактированный ответ. просто чтобы подтвердить, какой должен быть правильный результат в этом случае? –

+0

12.04.2017, поскольку ввод должен быть проанализирован как 12 апреля 2014 года вместо 4 декабря 2014 года, как это делает ASP.NET. – Lion

0

Если вы не возражаете, используя общий метод StatusCode, чтобы сделать этот вызов, вы можете сделать что-то вроде следующего:

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; 
    } 

Вы можете добавить это к основанию класс и назвать это нравится:

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

это до вас, если вы хотите создать свой собственный Ok, BadRequest, и т.д ... методы, но для меня это работает, и я надеюсь, что это помогает кому-то еще. Вы даже можете использовать код по умолчанию = 200, если большинство ваших запросов - GET. Этот код предполагает, что вы либо хотите ответить строкой, логическим или пользовательским объектом, но вы можете легко обрабатывать все примитивы, проверяя Type.GetTypeInfo(). IsPrimitive и даже выполняет некоторые проверки на десятичные значения, строку, DateTime, TimeSpan, DateTimeOffset , или Guid.

3

Я хотел форматировать даты в моих ответах, и я сделал следующее в методе ConfigureServices:

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

Надежда, что помогает.

0

У меня было такое же проблемное объявление, что я почти разозлился. Я все время пробовал без сучков.Сначала я нашел обходной путь, чтобы решить часть моей проблемы:

Обход:

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); 

Но, таким образом, я Визитки должен установить InvariantCulture всего моего DateTime. Я нашел решение, устанавливающее мою культуру в configure на startup.cs.

Набор культура на startup.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(); 
     } 

Надеется, что это поможет вам.

1

Была такая же проблема. При передаче DateTime в тело запроса работает отлично (поскольку Json-конвертер обрабатывает этот персонал), передача DateTime в строке запроса в качестве параметра имеет некоторые проблемы с культурой.

Мне не понравился подход «изменить все запросы культуры», так как это могло повлиять на разбор другого типа, что нежелательно.

Так что мой Choise был переопределить модель DateTime по умолчанию связывания с использованием IModelBinder: https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding

Что я сделал:

1) Определение пользовательского связующего (C# используются 7 синтаксиса для 'из' параметра) :

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) Определение поставщика для связующего:

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) И, наконец, зарегистрировать поставщика, который будет использоваться ASP.NET Ядра:

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

Теперь ваш DateTime будет разобран, как и ожидалось.

Смежные вопросы