2016-05-02 13 views
6

Ho bisogno di impostazioni JSON specifiche per controller nel mio ASP.NET MVC 6 webApi. Ho trovato questo campione che funziona (spero!) Per MVC 5: Force CamelCase on ASP.NET WebAPI Per ControllerImpostazioni JSON specifiche per controller su 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

Non si desidera ricevere le API con lo stesso nome delle classi del modello? Invece, li vuoi in pasalCase per ogni modello? –

+0

È solo un esempio per accedere all'oggetto 'JsonSerializerSettings'. Nel mio caso, ho bisogno di cambiare il raccoglitore per alcuni controller utilizzati da un'applicazione mobile – Karine

risposta

3

Questa classe funziona bene:

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

Usa:

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

Input/OutputFormatters non esistono più nel contesto delle risorse. Qualcuno sa come è possibile accedervi ora? –

+1

Vuoi anche la soluzione per "Microsoft.AspNetCore.Mvc.Filters". – HappyLiang

+0

forse per diverse versioni di framework è possibile utilizzare https://stackoverflow.com/a/44499722/782022 – aeroson

3

È possibile utilizzare un restituisce il tipo di JsonResult sui metodi di azione del controller. Nel mio caso, avevo bisogno di azioni specifiche per restituire Pascal Case per determinati scenari legacy. L'oggetto JsonResult consente di passare un parametro opzionale come JsonSerializerSettings.

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

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

    } 

Per avere più coerenti firme del metodo di controllo Ho finito per creare un metodo di estensione:

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

ora posso semplicemente chiamare il metodo di estensione all'interno del mio controller come di seguito:

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

Sì, anche quello che sto facendo - scenario simile: libreria legacy con dipendenze JS create con codice precedente a seconda di caso predefinito. Impossibile controllare il client delle impostazioni dell'app in modo corretto. Vorrei che ci fosse un modo diverso di fare questo per preservare l'interfaccia del contratto più semplice. –

+0

@RickStrahl Risposta modificata per includere un metodo di estensione per la gestione di questo. Un po 'più pulito. –