how to modify json result before sending back to client - json

My controller returns a JsonResult like that:
return Json(model);
How can I modify the json data on the fly before it is sent back to the client. I'd like to add validation attributes to my model so I end up with something like:
{"Label": "Test",
"ValidationRules":[{"data-val-required":"This field is required.", "data-val-length-max":25, "data-val-length":"Max 25 chars." }]}
UPDATE
public class Product
{
[Required]
String Label {get; set;}
}
when calling Json(model) with model being an instance of Product, I'd like to modify the json string before it is returned, so that it includes validation attributes.

Why not create a base class called ValidatableBase that has a ValidationRules property:
public class Product : ValidatableBase
{
public string Label { get; set; }
}
public abstract class ValidatableBase
{
public ValidatableBase()
{
this.ValidationRules = new Dictionary<string, string>();
}
public Dictionary<string, string> ValidationRules { get; set; }
}
public ActionResult GetProduct()
{
var product = new Product();
product.Label = "foo";
product.ValidationRules.Add("data-val-required", "this field is required");
return Json(product);
}
Inherit from this class and serialize.
Or if you're using DataAnnotations why not use the default jQuery validation and HtmlHelper methods provided by ASP.NET MVC?

Related

Properties with different names null when posting to MVC Controller but not WebApi Controller

I have a model called Purchase with various properties:
public class Purchase
{
[JsonProperty(PropertyName = "amount", NullValueHandling = NullValueHandling.Ignore)]
public int Amount
{
get;
set;
}
[JsonProperty(PropertyName = "currency_code", NullValueHandling = NullValueHandling.Ignore)]
public string CurrencyCode
{
get;
set;
}
}
The JSON is:
{
amount: 3000,
currency_code: "USD"
}
The controller is:
[AllowAnonymous]
public class ProtoController : Controller
{
private readonly IPurchaseManagerFactorySelector purchaseManagerFactorySelector = null;
public ProtoController(IPurchaseManagerFactorySelector purchaseManagerFactorySelector)
{
this.purchaseManagerFactorySelector = purchaseManagerFactorySelector;
}
[Route("opt/proto/index/{identifier}")]
[HttpGet]
public async Task<ActionResult> Index(string identifier)
{
return View();
}
[Route("opt/proto/index/{identifier}")]
[HttpPost]
public async Task<ActionResult> Index(string identifier, Request.Purchase purchase)
{
IPurchaseManager purchaseManager = purchaseManagerFactorySelector.GetFactory(identifier);
return View();
}
}
When the JSON is posted to an ApiController all the properties are populated correctly, however when the same JSON is posted to a Controller only Amount is populated - CurrencyCode is null. I briefly added a new property called Currency_Code and that was populated, it seems like the JsonProperty attribute is being ignore under MVC? I added the DataMember attribute, however that didn't have any effect so I removed it. Json.Net is being used, however I don't understand what the difference is?
I'd remove the Request.Purchase from the arguments and try the [FromBody] attribute for parameter binding.
If all you're changing is the Controller inheritence from Controller to ApiController than I'm not sure but it sounds like your message headers.
If you make the call in Chrome and use the inspect tools you should be able to inspect the headers in each call you make and see what's being populated

C# JSON data serialized and binded to DataGridView

I have this data class for storing data parsed from JSON formatted web data (using Json.NET library):
[Serializable()]
public class MovieData
{
public string FilePath { get; set; }
public string OrigName { get; set; }
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
[JsonProperty(PropertyName = "year")]
public int Year { get; set; }
[JsonProperty(PropertyName = "genres")]
public string[] Genres { get; set; }
}
The next class is for to be able serialize collection of MovieData objects:
[Serializable()]
[XmlRoot("MovieCollection")]
public class MovieCollection
{
[XmlArray("Movies")]
[XmlArrayItem("Movie", typeof(Movie))]
public List<Movie> movies = new List<MovieData>();
}
Finally, I need to bind such a collection of MovieData to DataGridView (or single MovieData object to DataGridViewRow), like:
dgvMovies.DataSource = movieCollection.movies;
Is it possible to bind it without hard-setting of DataGridViewColumn collection before? Native data types are not problem, problem is string[] Genres array, which I need to format it in DataGridView in some way, like:
"genres[0] / genres[0] / ... genres[n]"
At this moment, while simply setting DataSource to collectin, this array is ignored (is not displayed anyway).
In MovieData class, you can add the following property :
public string GenresAsString
{
get { return String.Join("/", Genres); }
set { Genres = value.Split('/'); }
}
You will surely have to improve the setter to make it more resilient (triming, removing empty genres) if you plan to let the user modify this value.
Else you can remove the setter.

ASP.NET WEB API JSON Polymorphism

JSON deserialization not working for polymorphic attribute behavior-
Sample code -
--MODEL
public class A
{
public string a_property { get; set; }
}
public class B : A
{
public string b_property { get; set; }
}
public class C
{
public A a { get; set; }
}
--API
public partial class TestController : ApiBaseController
{
[HttpGet]
public IHttpActionResult GetC()
{
return Ok<C>(new C(){a = new B(){a_property="test", b_property ="test1"}});
}
[HttpPost]
public IHttpActionResult SaveC(C c)
{
return Ok<C>(c);
}
}
--Web Route config
Config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects;
Config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
Config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.All;
From UI GetC API is called the object returned is C with attribute a of type B. It does have the type detail i.e. [$type A, assembly name]. When the same JSON is posted from client to call SaveC API the deserialized JSON is of type C but the attribute a is of type A instead of B.
I have searched the web but with no help, what am i missing?
JSON.net deserializer is just respecting your model, if you want specify the heritage level for your entity, you need to create a custom converter or you can work with an interface and just use a jsonconvert attribute.

Service Stack POST-Request Body-Format / Transformation

iam using a RequestClass with the Route anotation to call a Json-Client POST method.
Now, while the paramters are structured like this
public class GetTicketRequest: IReturn<JsonObject>
{
public string CartId {
get;
set;
}
public string PriceId {
get;
set;
}
}
The BackendAPI needs them to be nesten in "data" in the json request, so more like
{
"data":[
{"cartid":123,
"priceId":11}]
}
Is there any way to transfrom the request object for the body before calling
JsonServiceClient _restClient = new JsonServiceClient(baseUrl);
JsonObject oneResponse = _restClient.Post(options);
This solution is useful where many DTOs require to be wrapped & converted, and is highly reusable, with no changes to your existing DTOs.
You can convert the requests of the JsonServiceClient by overriding the methods that handle preparing the requests for sending. Which means implementing your own extended JsonServiceClient as given below.
If you want to do this for all verbs then you override it's Send<TResponse> methods (otherwise, if it's just for POST then uncomment the commented out code, and remove the Send methods).
public class MyJsonServiceClient : JsonServiceClient
{
public Dictionary<Type, Func<object, object>> DtoConverters = new Dictionary<Type, Func<object, object>>();
public MyJsonServiceClient() {}
public MyJsonServiceClient(string baseUri) : base(baseUri) {}
public MyJsonServiceClient(string syncReplyBaseUri, string asyncOneWayBaseUri) : base(syncReplyBaseUri, asyncOneWayBaseUri) {}
public override TResponse Send<TResponse>(object request)
{
return base.Send<TResponse>(ConvertRequest(request));
}
public override TResponse Send<TResponse>(string httpMethod, string relativeOrAbsoluteUrl, object request)
{
return base.Send<TResponse>(httpMethod, relativeOrAbsoluteUrl, ConvertRequest(request));
}
/*
public override TResponse Post<TResponse>(string relativeOrAbsoluteUrl, object requestDto)
{
return base.Post(relativeOrAbsoluteUrl, ConvertRequest(requestDto));
}
*/
object ConvertRequest(object request)
{
Type dtoType = request.GetType();
return (DtoConverters.ContainsKey(dtoType)) ? DtoConverters[dtoType](request) : request;
}
}
Usage:
So given this DTO:
[Route("/test", "POST")]
public class TicketRequest : IReturnVoid
{
public string CartId { get; set; }
public string PriceId { get; set; }
}
You simply add the converter:
var client = new MyJsonServiceClient("http://localhost:9000");
// Simple converter for TicketRequest
client.DtoConverters.Add(typeof(TicketRequest), dto => {
var d = (TicketRequest)dto;
return new {
data = new {
CartId = d.CartId.ToInt(),
PriceId = d.PriceId.ToInt()
}
};
});
client.Post(new TicketRequest { CartId = "123", PriceId = "456" });
i solved this issue using a typed data property
public class GetTicketRequest: IReturn<JsonObject>
{
public class TicketCreateData
{
public int priceId {
get;
set;
}
}
public string CartId {
get;
set;
}
public string PriceId {
get;
set;
}
public List<TicketCreateData> data {
get {
var list = new List<TicketCreateData>();
list.Add(new TicketCreateData {
priceId = this.PriceId.ToInt()
});
return list;
}
set {
data = value;
}
}
}
To notes on this:
if neede, use DataContract/DataMember(Name="") to rename fields or only do partial serializing
Do never use structs for, like in this case, the data class - they are not serializeable at all
in my spefici case data even needs to be an array, thats why i used the list

How to omit Get only properties in servicestack json serializer?

I have an object which I am de-serializing using ToJson<>() method from ServiceStack.Text namespace.
How to omit all the GET only propeties during serialization? Is there any attribute like [Ignore] or something that I can decorate my properties with, so that they can be omitted?
Thanks
ServiceStack's Text serializers follows .NET's DataContract serializer behavior, which means you can ignore data members by using the opt-out [IgnoreDataMember] attribute
public class Poco
{
public int Id { get; set; }
public string Name { get; set; }
[IgnoreDataMember]
public string IsIgnored { get; set; }
}
An opt-in alternative is to decorate every property you want serialized with [DataMember]. The remaining properties aren't serialized, e.g:
[DataContract]
public class Poco
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
public string IsIgnored { get; set; }
}
Finally there's also a non-intrusive option that doesn't require attributes, e.g:
JsConfig<Poco>.ExcludePropertyNames = new [] { "IsIgnored" };
Dynamically specifying properties that should be serialized
ServiceStack's Serializers also supports dynamically controlling serialization by providing conventionally named ShouldSerialize({PropertyName}) methods to indicate whether a property should be serialized or not, e.g:
public class Poco
{
public int Id { get; set; }
public string Name { get; set; }
public string IsIgnored { get; set; }
public bool? ShouldSerialize(string fieldName)
{
return fieldName == "IsIgnored";
}
}
More examples in ConditionalSerializationTests.cs
For nullable members, you also have the ability to set it to null before serializing.
This is particularly useful if you want to create a single view/api model that is re-used for several API calls. The service can touch it up before setting it on the response object.
Example:
public SignInPostResponse Post(SignInPost request)
{
UserAuthentication auth = _userService.SignIn(request.Domain, true, request.Username, request.Password);
// Map domain model ojbect to API model object. These classes are used with several API calls.
var webAuth = Map<WebUserAuthentication>(auth);
// Exmaple: Clear a property that I don't want to return for this API call... for whatever reason.
webAuth.AuthenticationType = null;
var response = new SignInPostResponse { Results = webAuth };
return response;
}
I do wish there was a way to dynamically control the serialization of all members (including non-nullable) on a per endpoint fashion.