How to reset serialization after each web api call

2020-07-30 03:34发布

问题:

I have used custom json serialization for a particular API call. But it overrides the global format. I need to reset this serialization after this API call or at the beginning of all other API calls.

public class ShouldSerializeContractResolver : CamelCasePropertyNamesContractResolver
{
    private List<Serializable> _serializables;

    public ShouldSerializeContractResolver(List<Serializable> serializable)
    {
        _serializables = serializable;
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        foreach (var item in _serializables)
        {
            if (item.ObjectType.Contains(property.DeclaringType) && !item.Serialize.Contains(property.PropertyName))
            {
                property.ShouldSerialize =
                   instance =>
                   {
                       return false;
                   };
            }
        }

        return property;
    }
}

And I called this serializer from API controller directly as shown below:

    var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;

    List<Serializable> serializableList = new List<Serializable>(); // Model class for storing list of Model classes and corresponding serializable objects as string
        List<Type> listObjectType = new List<Type>();
        List<string> serialize = new List<string>();

        listObjectType.Add(typeof(ModelClassName));
        serialize.Add("classObject1");
        serialize.Add("classObject2");
        serializableList.Add(new Serializable
        {
            Serialize = serialize,
            ObjectType = listObjectType
        });

    json.SerializerSettings.ContractResolver = new ShouldSerializeContractResolver(serializableList); // This is where the serializer is modified

回答1:

I've added a "ResetSerializeContractResolverFilter.cs" as a filter.

    public class ResetSerializeContractResolverFilter : System.Web.Http.Filters.ActionFilterAttribute
    {
    public ResetSerializeContractResolverFilter()
    {

    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
        json.SerializerSettings.ContractResolver = new DefaultContractResolver();
        base.OnActionExecuting(actionContext);
    }
    }

Then I included that filter from "Global.asax", Application_Start as shown below

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        // Add filter for resetting contractresolver
        var filters = System.Web.Http.GlobalConfiguration.Configuration.Filters;
        filters.Add(new ResetSerializeContractResolverFilter());
    }

Hence this filter will be invoked in each API call and gets the serializer to reset as Default.



回答2:

To use the ShouldSerializeContractResolver serializer in particular action, you can use serializerSettings property directly to the mehod along with the response.

public HttpResponseMessage Get(){
  List<Product> result = new List<Product>();
      //bind data to list
  var formatter = new JsonMediaTypeFormatter();
  var json =formatter.SerializerSettings;

  json.ContractResolver = new ShouldSerializeContractResolver();

  return Request.CreateResponse(HttpStatusCode.OK, result, formatter);
}