2016-05-02 8 views
6

Ich benötige spezifische JSON-Einstellungen pro Controller in meinem ASP.NET MVC 6 webApi. fand ich diese Probe, die (hoffentlich!) Für MVC 5 Werke: Force CamelCase on ASP.NET WebAPI Per ControllerSpezifische JSON-Einstellungen pro Controller unter ASP.NET MVC 6

using System; 
using System.Linq; 
using System.Web.Http.Controllers; 
using System.Net.Http.Formatting; 
using Newtonsoft.Json.Serialization; 

public class CamelCaseControllerConfigAttribute : Attribute, IControllerConfiguration 
{ 
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) 
{ 
    var formatter = controllerSettings.Formatters.OfType<JsonMediaTypeFormatter>().Single(); 
    controllerSettings.Formatters.Remove(formatter); 

    formatter = new JsonMediaTypeFormatter 
    { 
    SerializerSettings = {ContractResolver = new CamelCasePropertyNamesContractResolver()} 
    }; 

    controllerSettings.Formatters.Add(formatter); 

} 
} 
+0

Sie möchten Ihre API (s) nicht mit dem gleichen Namen wie Ihre Modellklassen erhalten? Stattdessen möchten Sie sie in PasalCase für jedes Modell? –

+0

Es ist nur ein Beispiel für den Zugriff auf das 'JsonSerializerSettings' -Objekt. In meinem Fall muss ich den Ordner für einen Controller ändern, der von einer mobilen Anwendung verwendet wird – Karine

Antwort

3

Diese Klasse funktioniert:

using System; 
using System.Linq; 
using Newtonsoft.Json.Serialization; 
using Microsoft.AspNet.Mvc.Filters; 
using Newtonsoft.Json; 
using Microsoft.AspNet.Mvc.Formatters; 

namespace Teedl.Web.Infrastructure 
{ 
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 

    public class MobileControllerConfiguratorAttribute : Attribute, IResourceFilter 
    { 
     private readonly JsonSerializerSettings serializerSettings; 

     public MobileControllerConfiguratorAttribute() 
     { 
      serializerSettings = new JsonSerializerSettings() 
      { 
       ContractResolver = new CamelCasePropertyNamesContractResolver(), 
       TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects, 
       TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple, 
       Binder = new TypeNameSerializationBinder("Teedl.Model.Mobile.{0}, Teedl.Model.ClientMobile") 
     }; 
     } 


     public void OnResourceExecuted(ResourceExecutedContext context) 
     { 
     } 

     public void OnResourceExecuting(ResourceExecutingContext context) 
     { 
      var mobileInputFormatter = new JsonInputFormatter(serializerSettings); 
      var inputFormatter = context.InputFormatters.FirstOrDefault(frmtr => frmtr is JsonInputFormatter); 
      if (inputFormatter != null) 
      { 
       context.InputFormatters.Remove(inputFormatter); 
      } 
      context.InputFormatters.Add(mobileInputFormatter); 

      var mobileOutputFormatter = new JsonOutputFormatter(serializerSettings); 
      var outputFormatter = context.OutputFormatters.FirstOrDefault(frmtr => frmtr is JsonOutputFormatter); 
      if (outputFormatter != null) 
      { 
       context.OutputFormatters.Remove(outputFormatter); 
      } 
      context.OutputFormatters.Add(mobileOutputFormatter); 
     } 
    } 
} 

Verwendung:

[Route("api/mobile/businessrequest")] 
[Authorize] 
[MobileControllerConfigurator] 
public class MobileBusinessRequestController : BaseController 
{ 
+4

Input/OutputFormatters existieren nicht mehr im Ressourcenkontext. Weiß jemand, wie sie jetzt zugegriffen werden können? –

+1

Wollen Sie auch die Lösung für "Microsoft.AspNetCore.Mvc.Filters". – HappyLiang

+0

vielleicht für verschiedene Framework-Versionen können Sie https://Stackoverflow.com/a/44499722/782022 – aeroson

3

Sie ein verwenden können Rückgabetyp von JsonResult für Ihre Controller-Aktionsmethoden. In meinem Fall brauchte ich spezielle Aktionen, um Pascal Case für bestimmte Legacy-Szenarien zurückzugeben. Mit dem JsonResult-Objekt können Sie einen optionalen Parameter als JsonSerializerSettings übergeben.

public IActionResult Get(string id) 
     { 
      var data = _service.getData(id); 
      return this.ToPascalCase(data); 
     } 

:

public JsonResult Get(string id) 
    { 
      var data = _service.getData(id); 

     return Json(data, new JsonSerializerSettings 
      { 
       ContractResolver = new DefaultContractResolver() 
      }); 

    } 

Um einheitlichere Steuerung Methodensignaturen habe ich am Ende eine Erweiterungsmethode zu schaffen: Ich kann

public static JsonResult ToPascalCase(this Controller controller, object model) 
     { 
      return controller.Json(model, new JsonSerializerSettings 
      { 
       ContractResolver = new DefaultContractResolver() 
      }); 
     } 

nun wie unten die Erweiterungsmethode in meinem Controller einfach anrufen

+0

Yup das ist, was ich auch tue - ähnliches Szenario: Legacy-Bibliothek, die JS-Abhängigkeiten hat, die mit älteren Code je nach gebaut wurden Standardfall. Kann App-Einstellungen nicht steuern Client erhält den richtigen Fall. Ich wünschte, es gäbe einen anderen Weg, um die einfachere Vertragsschnittstelle zu erhalten. –

+0

@RickStrahl Editierte Antwort, die eine Erweiterungsmethode für die Behandlung enthält. Ein bisschen sauberer. –