WCF custom serialization - json

I'm using .Net Framework WCF. This application receive json requests and response json string.
I would like to use my own serialization library for the serialization and deserialization actions.
In asp.net I used to do it in Global.asax file:
IJsonSerializer serializer = new Serializer();
GlobalConfiguration.Configuration.Formatters.Add(new CustomFormatter(serializer));
Here is my customer formatter class:
using System.Text;
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net;
using System.Threading.Tasks;
namespace Test.Formatters
{
public class CustomFormatter: MediaTypeFormatter
{
private readonly IJsonSerializer _serializer;
public CustomFormatter(IJsonSerializer serializer)
{
_serializer = serializer;
SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"));
SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/json"));
SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml"));
SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/xml"));
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}
public override bool CanReadType(Type type)
{
return true;
}
public override bool CanWriteType(Type type)
{
return true;
}
public override async Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
StreamReader reader = new StreamReader(readStream);
string text = await reader.ReadToEndAsync();
var serializedObj = _serializer.Deserialize(type, text);
return serializedObj;
}
public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
var serializedObj = _serializer.Serialize(value);
var encoding = Encoding.GetEncoding(content.Headers.ContentType.CharSet);
await writeStream.WriteAsync(encoding.GetBytes(serializedObj), 0, encoding.GetBytes(serializedObj).Length);
}
}
}
In .NetFramework WebAPI ReadFromStreamAsync and WriteToStreamAsync are triggered perfectly.
However, in WCF they are not triggered even though content-type is "application/json".
How can I handle WCF serialization by myself?

Related

ASP.NET MVC DataBinder not deserializing simple types from JSON

Input JSON:
{ "name": "gerry" }
Action method:
{ public ActionResult GenerateQrCode([FromBody] string name }
Problem:
The simple-type args are null
ModelState: Invalid
The built-in json deserializer can't handle the input in this form
I've tried:
ConfigureServices() -> services.AddControllersWithViews().AddNewtonsoftJson(); to switch to NewtonSoft, which I know/love
I've set a break-point into the non-NewtonSoft built-in MS SystemTextJsonInputFormatter.ctor() just to check, if it's still used: yes, it is, I'm not sure why, when I'm calling the above .AddNewtonsoftJson()
The situation:
The client POSTs all the input params as one JSON string document, which is UTF8 w/out BOM
The string comes in at the server-side and is nicely readable with new System.IO.StreamReader(Request.Body).ReadToEnd() from inside the immediate window
I need a way ASP.NET Core deserializes this, as it was able under the .NET4.X for many years w/out any issue
I wouldn't like to add [FromBody] and similar opt-in signatures all over the server actions/args
You pass the name as json but accept as a string so it will be null, you can use an InputFormatter like:
public class RawJsonBodyInputFormatter : InputFormatter
{
public RawJsonBodyInputFormatter()
{
this.SupportedMediaTypes.Add("application/json");
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
var request = context.HttpContext.Request;
using (var reader = new StreamReader(request.Body))
{
var content = await reader.ReadToEndAsync();
return await InputFormatterResult.SuccessAsync(content);
}
}
protected override bool CanReadType(Type type)
{
return type == typeof(string);
}
}
In startup.cs:
services
.AddMvc(options =>
{
options.InputFormatters.Insert(0, new RawJsonBodyInputFormatter());
});
And then you can get the row string
To deserilize it, you can check this, use Newtonsoft and make the string to a Model
[HttpPost]
public IActionResult GenerateQrCode([FromBody] string name)
{
object o = JsonConvert.DeserializeObject(name);
MyModel my = JsonConvert.DeserializeObject<MyModel>(o.ToString());
return View();
}

Any examples for jersey mvc feature with html?

In my application I am using backbone.js and underscore template. I am planning to use jersey mvc feature for single page application.How to render the html page from jersey mvc viewable object?
here I am using jersey mvc feature, i am not using any third party libraries and client side i am using backbone-marrionette js and underscore template. Please find below code snippet.
public class testSubResource {
private Logger log = LoggerFactory.getLogger(getClass());
#Context
private UriInfo uriInfo;
#Inject
private TestService service;
public TestSubResource(TestService service, UriInfo uriInfo) {
super();
this.service = service;
this.uriInfo = uriInfo;
}
#GET
#Template
#Produces({MediaType.TEXT_HTML})
public Viewable details(#PathParam("id") String id) {
log.info("get test details:{}", id);
JsonObject response = null;
try{
response = service.getTestDetails(id);
}
catch(Exception ex) {
throw ex;
}
return new Viewable("/test", response);
}}
Here it return the json response. I need to pass the json response to jsp...

WebApi Custom MediaTypeFormatter get posted parameters

I am calling a post action on a webapi by passing in a serialised JSON DTO.
I also have a custom media type formatter to encrypt the resulting data. However in the WriteToStreamAsync method, how can i get the posted parameters?
The custom media type formatter class
public class JsonFormatter : JsonMediaTypeFormatter
{
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
var taskSource = new TaskCompletionSource<object>();
try
{
if (value != null)
{
//How to get posted parameters?
}
}
catch (Exception e)
{
taskSource.SetException(e);
}
return taskSource.Task;
}
}
}
I managed to get it via the HttpContext.Current.Request.InputStream
Using HttpContext.Current generally should not work in this scenario since it won't always be available for async calls.
Instead do something like this:
public class JsonFormatter : JsonMediaTypeFormatter
{
private readonly HttpRequestMessage request;
public JsonFormatter() { }
public JsonFormatter(HttpRequestMessage request)
{
this.request = request;
}
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
return new JsonFormatter(request);
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
// logic referencing this.request
}
}

Newtonsoft JSON

I have created a New MVC4 Application and by default Newton JSON added to the Package.
I read that it is useful for serializing and deserializing JSON. Is this all it does ?
By default we can send JSON in MVC using JSONResult. and using Stringify in JQuery i can receive as a class in C#.
I know there should be some reason why they added Newton JSON.
As i am new to MVC and starting off new project want to know some insight of which serialize/deserialize to go for ?
Thanks
They added Newtonsoft so that your WebAPI controller can magically serialize your returned object. In MVC 3 we used to return our object like so:
public ActionResult GetPerson(int id)
{
var person = _personRepo.Get(id);
return Json(person);
}
In a Web API project you can return person and it will be serialized for you:
public Person GetPerson(int id)
{
var person = _personRepo.Get(id);
return person
}
Use JsonResult and return Json(yourObject) on a post operation, or Json(yourObject, JsonRequestBehavior.AllowGet) if you're doing a GET operation.
If you want to deserialize Json with the Newton Json.NET, check out http://www.hanselman.com/blog/NuGetPackageOfTheWeek4DeserializingJSONWithJsonNET.aspx
If your project was just an MVC project with no WebApi, then Newtonsoft.Json was not added for returning JsonResults as the JsonResult returned by MVC uses the JavaScriptSerializer as below:
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed);
}
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
{
response.ContentType = ContentType;
}
else
{
response.ContentType = "application/json";
}
if (ContentEncoding != null)
{
response.ContentEncoding = ContentEncoding;
}
if (Data != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
if (MaxJsonLength.HasValue)
{
serializer.MaxJsonLength = MaxJsonLength.Value;
}
if (RecursionLimit.HasValue)
{
serializer.RecursionLimit = RecursionLimit.Value;
}
response.Write(serializer.Serialize(Data));
}
}
In this case it was added because WebGrease has a dependency on it. And the bundling and minification services provided by MVC in System.Web.Optimization have a dependency on WebGrease.
So a default MVC app with no WebApi will have Newtonsoft.Json installed for bundling and minification services not WebApi.
To be clear the JsonResult returned by WebApi in System.Web.Http does use Newtonsoft.Json for it's serialization as below:
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
namespace System.Web.Http.Results
{
/// <summary>
/// Represents an action result that returns an <see cref="F:System.Net.HttpStatusCode.OK"/> response with JSON data.
/// </summary>
/// <typeparam name="T">The type of content in the entity body.</typeparam>
public class JsonResult<T> : IHttpActionResult
But Newtonsoft.Json is not included in a non WebApi, default MVC project just in case you might decide to use some WebApi, it's there because, as above, WebGrease needs it. Not sure what they're doing in vNext, probably Newtonsoft.Json.

ASP.net MVC returning JSONP

I am looking to return some JSON across domains and I understand that the way to do this is through JSONP rather than pure JSON.
I am using ASP.net MVC so I was thinking about just extending the JsonResult type and then extending the Controller so that it also implemented a Jsonp method.
Is this the best way to go about it or is there a built-in ActionResult that might be better?
Solution: I went ahead and did that. Just for reference sake I added a new result:
public class JsonpResult : System.Web.Mvc.JsonResult
{
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
{
response.ContentType = ContentType;
}
else
{
response.ContentType = "application/javascript";
}
if (ContentEncoding != null)
{
response.ContentEncoding = ContentEncoding;
}
if (Data != null)
{
// The JavaScriptSerializer type was marked as obsolete prior to .NET Framework 3.5 SP1
#pragma warning disable 0618
HttpRequestBase request = context.HttpContext.Request;
JavaScriptSerializer serializer = new JavaScriptSerializer();
response.Write(request.Params["jsoncallback"] + "(" + serializer.Serialize(Data) + ")");
#pragma warning restore 0618
}
}
}
and also a couple of methods to a superclass of all my controllers:
protected internal JsonpResult Jsonp(object data)
{
return Jsonp(data, null /* contentType */);
}
protected internal JsonpResult Jsonp(object data, string contentType)
{
return Jsonp(data, contentType, null);
}
protected internal virtual JsonpResult Jsonp(object data, string contentType, Encoding contentEncoding)
{
return new JsonpResult
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding
};
}
Works like a charm.
Here is a simple solution, if you don't want to define an action filter
Client side code using jQuery:
$.ajax("http://www.myserver.com/Home/JsonpCall", { dataType: "jsonp" }).done(function (result) {});
MVC controller action. Returns content result with JavaScript code executing callback function provided with query string. Also sets JavaScript MIME type for response.
public ContentResult JsonpCall(string callback)
{
return Content(String.Format("{0}({1});",
callback,
new JavaScriptSerializer().Serialize(new { a = 1 })),
"application/javascript");
}
Rather than subclassing my controllers with Jsonp() methods, I went the extension method route as it feels a touch cleaner to me. The nice thing about the JsonpResult is that you can test it exactly the same way you would a JsonResult.
I did:
public static class JsonResultExtensions
{
public static JsonpResult ToJsonp(this JsonResult json)
{
return new JsonpResult { ContentEncoding = json.ContentEncoding, ContentType = json.ContentType, Data = json.Data, JsonRequestBehavior = json.JsonRequestBehavior};
}
}
This way you don't have to worry about creating all the different Jsonp() overloads, just convert your JsonResult to a Jsonp one.
Ranju's blog post (aka "This blog post I found") is excellent, and reading it will allow you to further the solution below so that your controller can handle same-domain JSON and cross-domain JSONP requests elegantly in the same controller action without additional code [in the action].
Regardless, for the "give me the code" types, here it is, in case the blog disappears again.
In your controller (this snippet is new/non-blog code):
[AllowCrossSiteJson]
public ActionResult JsonpTime(string callback)
{
string msg = DateTime.UtcNow.ToString("o");
return new JsonpResult
{
Data = (new
{
time = msg
})
};
}
JsonpResult found on
this excellent blog post:
/// <summary>
/// Renders result as JSON and also wraps the JSON in a call
/// to the callback function specified in "JsonpResult.Callback".
/// http://blogorama.nerdworks.in/entry-EnablingJSONPcallsonASPNETMVC.aspx
/// </summary>
public class JsonpResult : JsonResult
{
/// <summary>
/// Gets or sets the javascript callback function that is
/// to be invoked in the resulting script output.
/// </summary>
/// <value>The callback function name.</value>
public string Callback { get; set; }
/// <summary>
/// Enables processing of the result of an action method by a
/// custom type that inherits from <see cref="T:System.Web.Mvc.ActionResult"/>.
/// </summary>
/// <param name="context">The context within which the
/// result is executed.</param>
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
response.ContentType = ContentType;
else
response.ContentType = "application/javascript";
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
if (Callback == null || Callback.Length == 0)
Callback = context.HttpContext.Request.QueryString["callback"];
if (Data != null)
{
// The JavaScriptSerializer type was marked as obsolete
// prior to .NET Framework 3.5 SP1
#pragma warning disable 0618
JavaScriptSerializer serializer = new JavaScriptSerializer();
string ser = serializer.Serialize(Data);
response.Write(Callback + "(" + ser + ");");
#pragma warning restore 0618
}
}
}
Note: Following up on the comments to the OP by #Ranju and others, I figured it was worth posting the "bare minimum" functional code from Ranju's blog post as a community wiki. Though it's safe to say that Ranju added the above and other code on his blog to be used freely, I'm not going to copy his words here.
For ASP.NET Core ,NOT ASP.NET MVC
This is a tailored version for ASP.NET CORE of the solution which exists in the answer
public class JsonpResult : JsonResult
{
public JsonpResult(object value) : base(value)
{
}
public override async Task ExecuteResultAsync(ActionContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
HttpResponse response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
response.ContentType = ContentType;
else
response.ContentType = "application/javascript";
if (Value != null)
{
HttpRequest request = context.HttpContext.Request;
string serializedJson = JsonConvert.SerializeObject(Value);
string result = $"{request.Query["callback"]}({serializedJson})";
await response.WriteAsync(result);
}
}
}
The referenced articles by stimms and ranju v were both very useful and made the situation clear.
However, I was left scratching my head about using extensions, sub-classing in context of the MVC code I had found online.
There was two key points that caught me out:
The code I had derived from ActionResult, but in ExecuteResult there was some code to return either XML or JSON.
I had then created a Generics based ActionResult, to ensure the same ExecuteResults was used independant of the type of data I returned.
So, combining the two - I did not need further extensions or sub-classing to add the mechanism to return JSONP, simply change my existing ExecuteResults.
What had confused me is that really I was looking for a way to derive or extend JsonResult, without re-coding the ExecuteResult. As JSONP is effectively a JSON string with prefix & suffix it seemed a waste. However the underling ExecuteResult uses respone.write - so the safest way of changing is to re-code ExecuteResults as handily provided by various postings!
I can post some code if that would be useful, but there is quite a lot of code in this thread already.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
namespace Template.Web.Helpers
{
public class JsonpResult : JsonResult
{
public JsonpResult(string callbackName)
{
CallbackName = callbackName;
}
public JsonpResult()
: this("jsoncallback")
{
}
public string CallbackName { get; set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
var request = context.HttpContext.Request;
var response = context.HttpContext.Response;
string jsoncallback = ((context.RouteData.Values[CallbackName] as string) ?? request[CallbackName]) ?? CallbackName;
if (!string.IsNullOrEmpty(jsoncallback))
{
if (string.IsNullOrEmpty(base.ContentType))
{
base.ContentType = "application/x-javascript";
}
response.Write(string.Format("{0}(", jsoncallback));
}
base.ExecuteResult(context);
if (!string.IsNullOrEmpty(jsoncallback))
{
response.Write(")");
}
}
}
public static class ControllerExtensions
{
public static JsonpResult Jsonp(this Controller controller, object data, string callbackName = "callback")
{
return new JsonpResult(callbackName)
{
Data = data,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
public static T DeserializeObject<T>(this Controller controller, string key) where T : class
{
var value = controller.HttpContext.Request.QueryString.Get(key);
if (string.IsNullOrEmpty(value))
{
return null;
}
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
return javaScriptSerializer.Deserialize<T>(value);
}
}
}
//Example of using the Jsonp function::
// 1-
public JsonResult Read()
{
IEnumerable<User> result = context.All();
return this.Jsonp(result);
}
//2-
public JsonResult Update()
{
var models = this.DeserializeObject<IEnumerable<User>>("models");
if (models != null)
{
Update(models); //Update properties & save change in database
}
return this.Jsonp(models);
}
the solution above is a good way of working but it should be extendend with a new type of result instead of having a method that returns a JsonResult you should write methods that return your own result types
public JsonPResult testMethod() {
// use the other guys code to write a method that returns something
}
public class JsonPResult : JsonResult
{
public FileUploadJsonResult(JsonResult data) {
this.Data = data;
}
public override void ExecuteResult(ControllerContext context)
{
this.ContentType = "text/html";
context.HttpContext.Response.Write("<textarea>");
base.ExecuteResult(context);
context.HttpContext.Response.Write("</textarea>");
}
}