Setting IgnoreSerializableAttribute Globally in Json.net - json.net

I'm working on a ASP.NET WebApi (Release Candidate) project where I'm consuming several DTOs that are marked with the [Serializable] attribute. These DTOs are outside of my control so I'm not able to modify them in any way. When I return any of these from a get method the resulting JSON contains a bunch of k__BackingFields like this:
<Name>k__BackingField=Bobby
<DateCreated>k__BackingField=2012-06-19T12:35:18.6762652-05:00
Based on the searching I've done this seems like a problem with JSON.NET's IgnoreSerializableAttribute setting and to resolve my issue I just need to set it globally as the article suggests. How do I change this setting globally in a ASP.NET Web api project?

I found easy way to get rid of k__BackingField in the names.
This fragment should be somewhere in the Application_Start() in Global.asax.cs:
JsonSerializerSettings jSettings = new Newtonsoft.Json.JsonSerializerSettings();
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = jSettings;
Looks like the default setting takes care of it.

Since the library does not expose a static setter for the DefaultContractResolver, I suggest you create a static wrapper over JsonConvert and it's Serialize*/Deserialize* methods (at least the ones you use).
In your static wrapper you can define a static contract resolver:
private static readonly DefaultContractResolver Resolver = new DefaultContractResolver
{
IgnoreSerializableAttribute = true
};
This you can pass to each serialization method in the JsonSerializerSettings, inside your wrapper.
Then you call your class throughout your project.
The alternative would be to get the JSON.NET source code and adjust it yourself to use that attribute by default.

For me, the following fixed the issue with circular references and k__BackingField.
In your WebApiConfig add the following to the Register() method:
JsonSerializerSettings jSettings = new Newtonsoft.Json.JsonSerializerSettings {
ContractResolver = new DefaultContractResolver {
IgnoreSerializableAttribute = true
},
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = jSettings;

Friends, don't declare properties like this:
public String DiscretionCode { get; set; }
But, create auxiliar vars, like old....
private String discretionCode;
public String DiscretionCode
{
get { return discretionCode;}
set { discretionCode = value; }
}

Related

Is it possible to configure Newtonsoft.Json to ignore propreties with [ScriptIgnore] attribute

I have a third-party class (lets call it Class1) which I need to serialize to JSON. If I try to do this as is, I either receive StackOverflowException or JsonSerializationException with message "Self referencing loop detected with type". I've tried to apply the following settings for the JsonConvert but it didn't help me to avoid StackOverflowException
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.None,
PreserveReferencesHandling = PreserveReferencesHandling.None,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
After decompiling the Class1 I found out that a lot of properties of the Class1 are marked with [ScriptIgnore] attribute which is an analogue of [JsonIgnore] and is used by System.Web.Script.Serialization.JavaScriptSerializer but I need to use Newtonsoft serializer.
As far as Class1 is a third-party class I can't add [JsonIgnore] attribute to the needed properties.
I know that I can develop my own implementation of IContractResolver, and handle the problematic properties there, but I'd like to avoid this option.
Maybe there is a way somehow configure Newtonsoft serializer to take into consideration [ScriptIgnore] attribute as well as [JsonIgnore]. And do this configuration like it is done with ReferenceLoopHandling?
I would appreciate for any ideas.
There's no configuration option for this. If you search on github, ScriptIgnoreAttribute doesn't even appear in the Json.NET source tree.
Even though you don't want to implement your own IContractResolver, this would be the straightforward solution and very easy. First, define the following subclass of DefaultContractResolver as follows:
public class ScriptIgnoreContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (!property.Ignored)
{
if (property.AttributeProvider.GetAttributes(true).Any(p => p.GetType().FullName == "System.Web.Script.Serialization.ScriptIgnoreAttribute"))
{
property.Ignored = true;
}
}
return property;
}
}
Then serialize as follows:
// Define a static member
static readonly IContractResolver myResolver = new ScriptIgnoreContractResolver();
// And use it in your serialization method
var settings = new JsonSerializerSettings
{
ContractResolver = myResolver,
};
var json = JsonConvert.SerializeObject(rootObject, settings);
You may want to cache the contract resolver for best performance.

Setting OData result Page Size at runtime in WebAPI app

I am writing an ASP.NET Web API 2 web service using OdataControllers I have found out how to set page size using the PageSize Property of the EnableQueryAttribute. I want to allow the users of my web service to set the page size in the app.config and then have the application read this setting and set the page size. The problem is that using the attribute requires Page Size be set to a compile time constant.
Usage of attribute:
[EnableQuery(PageSize = 10)]
public IHttpActionResult GetProducts()
{
return repo.GetProducts();
}
One proposed solution I have seen is to construct the EnableQueryAttribute and set it on the HTTPConfiguration config object like this
int customSize = ReadPageSizeSettingFromConfigFile();
var attr = new EnableQueryAttribute { PageSize = customSize };
config.AddODataQueryFilter(attr);
but this doesn't actually work. The HttpConfiguration's Filter collection remains empty.
A comment on another post (buried in a list of comments) suggested removing all the EnableQuery attributes on the controllers but that has no effect either. Since the EnableQuery attribute replaced the older Queryable attribute I am wondering if this is a Microsoft problem.
This question has been asked and not answered before: How limit OData results in a WebAPI
All help is greatly appreciated.
You can use $top and $skip to achieve your goal, if client want pagesize is 10, and want the second page:
localhost/odata/Customers?$top=10&$skip=10
About dynamically set the pagesize:
public class MyEnableQueryAttribute : EnableQueryAttribute
{
public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions)
{
int pagesize = xxx;
var result = queryOptions.ApplyTo(queryable, new ODataQuerySettings { PageSize = pagesize });
return result;
}
}
and put this attribute in your controller method.
You can set config for MaxTop in webApiConfig resgister method
public static class WebApiConfig{
public static void Register(HttpConfiguration config){
config.Select().Expand().Filter().OrderBy().MaxTop(100).count() // you can change max page size here
}
}
I was able to accomplish this by creating a new attribute (I called it ConfigurableEnableQueryAttribute) that extends the enable query attribute. In the constructor for that attribute, load your config file and set any settings you are interested in in the base. Personally I loop through all settings provided in an "OData" section of my appsettings, and if there are matching settings in the EnableQuery attribute, I cast them to the specified type and supply them, but you can only look for specific settings if you want.
My attribute:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class ConfigurableEnableQueryAttribute : EnableQueryAttribute
{
public ConfigurableEnableQueryAttribute()
{
var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
var configuration = builder.Build();
var configProps = configuration.GetSection("OData").GetChildren();
var baseProps = typeof(EnableQueryAttribute).GetProperties();
foreach (var configProp in configProps)
{
var baseProp = baseProps.FirstOrDefault(x => x.Name.Equals(configProp.Key));
if (baseProp != null)
{
baseProp.SetValue(this, Convert.ChangeType(configProp.Value, baseProp.PropertyType));
}
}
}
}
and then in the controller
[HttpGet]
[ConfigurableEnableQuery]
public IQueryable<T> Get()
{
return _context.Set<T>().AsQueryable();
}

Asp.Net Web Api - attribute for not binding/formatting a parameter?

I have a method on an ApiController that looks like this:
public IEnumerable<Items> GetSlideSets() {
IServiceClass serviceClass = new ServiceClass();
//...
Yes, I am aware that this is not good design but I'm addressing this issue in a different iteration.
At a certain point in my application I need to call this functionality from within the project itself so I thought I could simply reuse the controller (and why not, I can pluck it out of my IoC container). The only problem is that in this case, I need to inject my own implementation of IServiceClass, easy enough:
public IEnumerable<Items> GetSlideSets(IServiceClass serviceClass = null) {
serviceClass = serviceClass ?? new ServiceClass();
//...
Except now I am getting errors when calling this via a regular Api call Optionalparameter 'serviceClass' is not supported by FormatterParameterBinding.
I know that there are various attributes that control bindings. Is there one that I can put on the parameter to say it shouldn't bind.
Like others have mentioned, it's probably a better idea to inject the dependency in the constructor.
But if you really must avoid binding an action parameter, there isn't a built-in attribute but you can create one pretty easily. Here's what it could look like:
public class DontBindAttribute : ParameterBindingAttribute
{
public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
{
return new DontBindParameterBinding(parameter);
}
private class DontBindParameterBinding : HttpParameterBinding
{
public DontBindParameterBinding(HttpParameterDescriptor parameter) : base(parameter)
{
}
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
{
actionContext.ActionArguments.Add(Descriptor.ParameterName, Descriptor.DefaultValue);
var completedTaskSource = new TaskCompletionSource<object>();
completedTaskSource.SetResult(null);
return completedTaskSource.Task;
}
}
}
You just need to apply the attribute to the parameter afterwards:
public IEnumerable<Items> GetSlideSets([DontBind] IServiceClass serviceClass = null)

Using Microsoft Unity IOC, how can you pass it an existing object to inject?

So if I have:
public class CustomerViewModel
{
public CustomerViewModel(ICustomer customer)
{
this.customer = customer
}
}
then is there a way to achieve:
ICustomerViewModel customerViewModel = container.Resolve<ICustomerViewModel>(existingCustomer);
If you want to build-up an existing instance through property and method injection, you can use the following:
var model = new CustomerViewModel(customer);
model = container.BuildUp(model);
In general I would not recommend using this feature of Unity. Sometimes you need it, but it's usually a warning sign that could be fixed by adjusting the design a bit to work more naturally with IoC as a pattern (not a framework). With more details on how you are using it, the SO community can probably offer some other options...
Since the dependency injection container is designed to provide finished objects, you'll need to use a factory pattern (which is quite common in these cases) to achieve your desired configuration:
public interface ICustomerViewModelFactory {
public ICustomerViewModel GetModelFor(ICustomer customer);
}
public class CustomerViewModelFactory : ICustomerViewModelFactory {
public ICustomerViewModel GetModelFor(ICustomer customer) {
return new CustomerViewModel(customer);
}
}
// elsewhere...
container.RegisterInstance<ICustomerViewModelFactory>(new CustomerViewModelFactory());
// and finally...
ICustomerViewModelFactory factory = container.Resolve<ICustomerViewModelFactory>();
ICustomerViewModel customerViewModel = factory.GetModelFor(existingCustomer);
Check the 'Can I pass constructor parameters to Unity's Resolve() method?' question (also on Stack Overflow).

Is it possible to remove properties from a dynamic class?

I have a dynamic ActionScript Class that is used to send parameters to a WebService. Some of these parameters are always present, so they are public properties of the Class:
package
{
[Bindable]
public dynamic class WebServiceCriteria
{
public var property1:int;
public var property2:String;
public var property3:String;
public var property4:String;
}
}
But, I am also adding properties at runtime that can change over time:
criteria.runTimeProperty = "1";
I'm not very familiar with using dynamic classes, so I was wondering if it is possible to "remove" the new property. Let's say the next time I call the WebService I don't want that property sent - not even as a null. How can I remove it from the Class instance without creating a new instance each time?
I believe all you'd need to do is this:
delete criteria.runTimeProperty;
or
delete criteria["runTimeProperty"];
Either should do the same thing.
See the delete documentation for specifics.

Resources