2016-05-05 2 views
2

Я пытаюсь создать атрибут, который будет сериализовать возврат данных от действия по-разномуWebAPI Временно Override JsonFormatter от OnActionExecuted

public override void OnActionExecuted(HttpActionExecutedContext filterContext) 
{ 
    var content = (filterContext.Response.Content as ObjectContent); 

    if (content == null) 
    { 
     return; 
    } 

    if (content.ObjectType.IsGenericType 
     && content.ObjectType.GetGenericTypeDefinition() == typeof (Page<>)) 
    { 
     var pageObject = (content.Value as IPage); 
     var jsonFormatterRule = new JsonFormatterRule(); 
     var pageJson = JsonConvert.SerializeObject(pageObject.ItemsArray, 
               jsonFormatterRule.GetPascalCasedSettings()); 

     //How do I set the content that \/ doesn't compile? 
     //filterContext.Response.Content = pageJson; 
    } 
} 

Это является JsonFormatterRules упаковывают кто хотел их видеть.

public JsonSerializerSettings GetDefaultSettings() 
{ 
    var settings = new JsonSerializerSettings() 
    { 
     Formatting = Formatting.Indented, 
     ContractResolver = new CamelCasePropertyNamesContractResolver(), 
     DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind, 
    }; 

    settings.Converters.AddRange(defaultConfiguredConverters); 
    return settings; 
} 

public JsonSerializerSettings GetPascalCasedSettings() 
{ 
    var settings = this.GetDefaultSettings(); 
    settings.ContractResolver = new DefaultContractResolver(); 

    return settings; 
} 

Как я могу установить содержимое с момента выполнения? Я не могу поменять сериализатор по умолчанию на DefaultContract Globally, потому что он может пронизывать проблемы.

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

+0

Что именно вы хотите сделать? У вас есть другой сериализатор для некоторых действий? – dotctor

+0

@dotctor Yeah Разный Сериализатор от некоторых действий, основанных на атрибуте –

ответ

1

Один из способов сделать это - определить пользовательский форматтер.

Во-первых, определить свой атрибут:

[AttributeUsage(AttributeTargets.Class)] 
public sealed class SpecialSerializeAttribute : Attribute 
{ 
} 

Теперь создать форматчик, который будет найти атрибут:

public class SpecialSerializeFormatter : MediaTypeFormatter 
{ 
    public SpecialSerializeFormatter() 
    { 
     //You can add any other supported types here. 
     this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json")); 
    } 

    public override bool CanReadType(Type type) 
    { 
     //you can just return false if you don't want to read any differently than your default way 
     //if you return true here, you should override the ReadFromStreamAsync method to do custom deserialize 
     return type.IsDefined(typeof(SpecialSerializeAttribute), true)); 
    } 

    public override bool CanWriteType(Type type) 
    { 
     return type.IsDefined(typeof(SpecialSerializeAttribute), true)); 
    } 

    public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, 
     TransportContext transportContext) 
    { 

     //value will be your object that you want to serialize 

     //add any custom serialize settings here 
     var json = JsonConvert.SerializeObject(value); 

     //Use the right encoding for your application here 
     var byteArray = Encoding.UTF8.GetBytes(json); 
     await writeStream.WriteAsync(byteArray, 0, byteArray.Length); 
    } 
} 

Регистрация форматера в вас WebApiConfig.cs

Вы также можете построить форматтер для каждого типа напрямую, а затем вам не нужно выполнять атрибут. Просто измените методы CanRead и CanWrite. Я нахожу, что основы этих прямых типов дают лучшие результаты, так как это не такой общий форматтер, и вам может потребоваться применять пользовательскую логику на основе типа, но приведенный выше ответ должен предоставить вам то, что вам нужно.

+0

Вау, я даже не знал, что вы могли бы это сделать. Я собираюсь проверить это сейчас –

0

Incase кто-то задавался вопросом, Response Содержимое HTTPContent, которое наследуется от ByteArrayContent. Поэтому, если у вас уже есть сериал JSON Serialized, все, что вам нужно сделать, это поместить его в массив байтов.

filterContext.ActionContext.Response.Content = new ByteArrayContent(Encoding.ASCII.GetBytes(pageJson)); 
+1

Полезно знать. Убедитесь, что ASCII - это то, что вы хотите. Если у вас есть пользовательский контент, который сериализуется, вам понадобится UTF8, чтобы любые специальные символы могли быть сериализованы. – ManOVision

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

  • Нет связанных вопросов^_^