2016-08-01 29 views
2

Ich habe ein WebAPI-Projekt, das ISO-Datumszeichenfolgen in das Eingabemodell aufnimmt. Ich habe diese unter Verwendung DateTimeOffset? analysiert. Ich möchte BCL-Datumsangaben aus meinem Projekt verbannen, also möchte ich einen Weg finden, diese Zeichenfolgen direkt an Instant zu binden.Binden von NodaTime Instant-Feld in einem InputModel-Textkörper mit C# ASP.NET WebAPI 2.0

public class MyInputModel 
{ 
    public DateTimeOffset? OldTime { get; set; } 

    public Instant NewTime { get; set; } 
} 

Ein Beispiel JSON Eingabemodell sieht wie folgt aus:

{ 
    "oldtime":"2016-01-01T12:00:00Z", 
    "newtime":"2016-01-01T12:00:00Z" 
} 

Und mein Controller-Code ist:

[HttpPost] 
public async Task<IActionResult> PostTimesAsync([FromBody]MyInputModel input) 
{ 
    Instant myOldTime = Instant.FromDateTimeUtc(input.oldTime.Value.UtcDateTime); 
    Instant myNewTime = input.newTime; // This cannot be used with ISO date strings. 
} 

ich wie folgt ein benutzerdefiniertes Modell Bindemittel zu bauen versucht. Dies funktioniert für Modelle in der Abfragezeichenfolge, nicht jedoch für solche im Hauptteil einer POST-Anforderung. Wie kann ich Datumseingaben in einem ISO 8601 String-Format an einen NodaTime Instant binden? (In WebApiConfigRegister Methode)

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     config.BindParameter(typeof(Instant), new InstantModelBinder()) 
     ... 
    } 
} 

WebApiConfig.Register heißt in Configuration Funktion in Startup.cs Datei:

public Task BindModelAsync(ModelBindingContext bindingContext) 
{ 
    if (!String.IsNullOrWhiteSpace(bindingContext.ModelName) && 
      bindingContext.ModelType == typeof(Instant?) && 
      bindingContext.ValueProvider.GetValue(bindingContext.ModelName) != null) 
    { 
     Instant? value; 
     var val = bindingContext.ValueProvider 
.GetValue(bindingContext.ModelName).FirstValue as string; 

     if (String.IsNullOrWhiteSpace(val)) 
     { 
      bindingContext.Result = ModelBindingResult.Failed(); 
      return Task.FromResult(0); 
     } 
     else if (InstantExtensions.TryParse(val, out value)) 
     { 
      bindingContext.Result = ModelBindingResult.Success(value); 
      return Task.FromResult(0); 
     } 
     else 
     { 
      bindingContext.ModelState.AddModelError(bindingContext.ModelName, 
"The date is invalid."); 
     } 
    } 

    bindingContext.Result = ModelBindingResult.Failed(); 
    return Task.FromResult(0); 
} 

public static bool TryParse(string value, out Instant? result) 
{ 
    result = null; 

    // If this is date-only, add Utc Midnight to the value. 
    if (value.Length.Equals(10)) 
    { 
     value += "T00:00:00Z"; 
    } 

    // Trim milliseconds if present 
    var decimalPointIndex = value.IndexOf('.'); 
    if (decimalPointIndex > 0) 
    { 
     value = value.Substring(0, decimalPointIndex) + "Z"; 
    } 

    // Attempt to parse 
    var parseResult = InstantPattern.GeneralPattern.Parse(value); 
    if (parseResult.Success) 
    { 
     result = parseResult.Value; 
     return true; 
    } 

    return false; 
} 
+0

Für welchen Typ haben Sie Ihren Modellbinder registriert? –

+0

Hallo Aram, ich habe es nicht registriert - in den Abfragezeichenfolgen verwende ich es wie folgt: '[ModelBinder (BinderType = typeof (InstantModelBinder))] Instant? time = null) ' – Ivan

+0

Versuchen Sie diese' ModelBinders.Binders.Add (typeof (Instant?), neue InstantModelBinder()); 'in' Global.asax.cs' Oder vielleicht ohne Fragezeichen, wie ich in 'MyInputModel 'Es ist nicht nullbar. –

Antwort

1

Sie sollten Ihr Modell Bindemittel wie folgt hinzufügen. In den meisten Fällen wie folgt aus:

var config = new HttpConfiguration(); 
WebApiConfig.Register(config); 

Wenn es nicht aufgerufen wird, können Sie fügen Sie einfach diese Zeile:

config.BindParameter(typeof(Instant), new InstantModelBinder())

wo HttpConfiguration Objekt wird in Startup.cs geschaffen.

+0

Entschuldigung - ich weiß immer noch nicht, wohin das gehen soll. Wird diese Methode von der Startup-Klasse aufgerufen? – Ivan

+0

Ja, Sie sollten dies in Ihrer Startup-Klasse haben, oder vielleicht ähnliches, Sie brauchen nur 'HttpConfiguration object', um' BindParameter' aufzurufen. –

+0

Ich habe eine 'Configure' Methode, aber keine Verweise auf' HttpConfiguration' und wenn ich versuche 'var config = new HttpConfiguration();' Ich kann den Namensraum dafür nicht finden - es ist ein großes Projekt, das wir noch nicht haben die relevanten Pakete installiert; Ich denke, das ist die falsche Herangehensweise? – Ivan