This post does not resolve the issue: ResponseExceptionMapper in cxf client . You will notice that I did in fact register and annotate my Provider, and I tried with WebApplicationException as suggested instead of Exception/CustomException.
Problem Statement: Unable to implement custom client side exception handler using Client (javax.ws.rs.client.Client) API, and #Provider class implementing the ResponseExceptionMapper interface.
Questions:
Does Client API not support custom client side providers for exception handling?
Any literature I looked up for this problem statement uses JAXRSClientFactory implementation; I'm yet to find any using Client API for this scenario. Would I have to switch my implementation?
What is the difference between Client API and JAXRSClientFactory implementations?
I am working on a cxf Client API implementation in Java, and noticed that for http status codes above 300 cxf wraps the Response in either a WebApplicationException or ProcessingException (depending upon the response status code). The server in my case has a customized response body indicating the actual reason for an http status code !200, like below (for response code = 412):
{
"requestError": {
"serviceException": {
"messageId": "SVC4120",
"text": "Invalid Request: Invalid Coupon Code."
}
}
}
Unfortunately the WebApplicationException itself does not render this. Instead the only message captured in the exception directly is a generic "412 Precondition Failed". I can do something similar to below exception block from code snippet (includes Client API code snippet):
protected RESPOBJ invoke(String endPointUrl) throws CustomException {
Object reqPOJO = prepareRequest();
try {
if(client == null) {
ClientBuilder builder = ClientBuilder.newBuilder();
//register custom JAX-RS components
builder.register(new CustomMapper());
}
WebTarget target = client.target(endPointUrl);
//do this when queryParams exist
if(!getUriParams().isEmpty()) {
for(Map.Entry<String, String> queryParams : getUriParams().entrySet()) {
target = target.queryParam(queryParams.getKey(), queryParams.getValue());
}
}
Invocation.Builder builder = target.request();
//create headers here
MultivaluedMap<String, Object> headers = new MultivaluedHashMap<>();
if(isBasicAuthRequired()) {
headers.add(AUTH_HEADER_PARAM, getBasicAuthentication());
}
headers.add(CONTENT_TYPE, getMediaType().toString());
builder.headers(headers);
builder.accept(getMediaType().toString());
//GET or POST
if(HttpMethodType.GET.equals(getHttpMethod())) {
return builder.get(RESPOBJ.class);
}
return builder.post(Entity.entity(reqPOJO, getMediaType()), RESPOBJ.class);
}
catch (Exception ex) {
if(ex instanceof ResponseProcessingException) {
ResponseProcessingException e = (ResponseProcessingException) ex;
logger.error("Unmarshalling failed: [" + e.getResponse().readEntity(String.class) + "]");
}
else if(ex instanceof WebApplicationException) {
WebApplicationException e = (WebApplicationException) ex;
logger.error("Error Response: ["+e.getResponse().readEntity(String.class) + "]");
}
throw new CustomException(ex);
}
}
However, I am looking to implement something cleaner, preferably using a custom Exception handler that implements ResponseExceptionMapper<> interface. From literature I noticed the only implementations of ResponseExceptionMapper for custom client side exception handling are using JAXRSClientFactory. My current implementation however uses the Client API (code snippet below). From a design aspect I will modify this to have a separate CustomExceptionMapper class that would be the Provider only for Exception cases, but I do not see why this Custom class is registered as a Provider (works for 200 status codes as MBR, and the MBW works always) but does not work for exception cases.
Update: While debugging and observing changes between a 200 vs >300 status code (412 in my case), I noticed that for 200 case JAXRSUtils.readFromMessageBodyReader() method gets invoked, which for the 1st time retrieves the Custom Provider. The code never gets here for status codes shown below in code snippet which should be the reason for not finding the CustomMapper. Is there any difference in how I must register my CustomExceptionMapper? Or does the Client API simply not support this functionality?
// for failure case the method above returns null (status > 300), whereas for success 200 case it executes method in last line and gets the provider.
// AbstractClient class that invokes the doReadEntity() method which in turn invokes and finds the Provider in JAXRSUtils.readFromMessageBodyReader() method code
protected <T> T readBody(Response r, Message outMessage, Class<T> cls,
Type type, Annotation[] anns) {
if (cls == Response.class) {
return cls.cast(r);
}
int status = r.getStatus();
//this is invoked for failure case
if ((status < 200 || status == 204) && r.getLength() <= 0 || status >= 300) {
return null;
}
//this for 200 status code
return ((ResponseImpl)r).doReadEntity(cls, type, anns);
}
//My custom provider code
#Provider
#Consumes
#Produces(MediaType.APPLICATION_JSON)
public class CustomMapper implements MessageBodyReader<CustomResponse>, MessageBodyWriter<CustomRequest>, ResponseExceptionMapper<CustomException> {
private Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
#Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return type.isAssignableFrom(CustomResponse.class);
}
#Override
public CustomResponse readFrom(Class<CustomResponse> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
CustomResponse respObj = new CustomResponse();
//json to pojo code
return respObj;
}
#Override
public long getSize(CustomRequest reqObj, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return -1;
}
#Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return type.isAssignableFrom(CustomRequest.class);
}
#Override
public void writeTo(CustomRequest reqObj, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
entityStream.write(gson.toJson(reqObj).getBytes());
}
#Override
public CustomException fromResponse(Response exceptionResponse) {
//Response obj to my CustomException code
return (CustomException);
}
}
Questions:
I'm trying to figure out what is done wrong here, and if Client API does not support custom client side exception handling for any reason?
What is the difference between Client API and JAXRSClientFactory implementations?
I also am looking into possibly using ClientResponseFilter (haven't tried this yet).
Any help appreciated. Thanks.
I have a Spring Boot Filter that I'm using to authenticate using Jwt. If successful, everything works great and I send out a Json response of my design. However, if the Authorization header is missing or incorrect, I throw a ServletException with a custom message. This results in an ugly Json that looks like this:
{
"timestamp":1453192910756,
"status":500,
"error":"Internal Server Error",
"exception":"javax.servlet.ServletException",
"message":"Invalid Authorization header.",
"path":"/api/test"
}
I wish to customize this Json so it takes the standard form I'm using for all my other responses.
My Filter code is here:
public class JwtFilter extends GenericFilterBean {
#Override
public void doFilter(final ServletRequest req,
final ServletResponse res,
final FilterChain chain) throws IOException, ServletException {
System.out.println("JwtFilter");
final HttpServletRequest request = (HttpServletRequest) req;
final String authHeader = request.getHeader("Authorization");
if (authHeader == null) {
throw new ServletException("Missing Authorization header.");
}
if (!authHeader.startsWith("Bearer ")) {
throw new ServletException("Invalid Authorization header.");
}
final String token = authHeader.substring(7);
try {
final Claims claims = Jwts.parser().setSigningKey("secretkey")
.parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
}
catch (final SignatureException e) {
throw new ServletException("Invalid token.");
}
chain.doFilter(req, res);
}
}
I tried using a wrapper to wrap the response but that didn't work. Another SO post said the response was not changeable but that wouldn't even make sense.
I think the correct way would be to edit the ServletResponse res but I couldn't get it to work.
Thanks!
EDIT: Kind of hacky but it works. If there's a better way, please answer:
public class JwtFilter extends GenericFilterBean {
#Override
public void doFilter(final ServletRequest req,
final ServletResponse res,
final FilterChain chain) throws IOException, ServletException {
System.out.println("JwtFilter");
final HttpServletRequest request = (HttpServletRequest) req;
final String authHeader = request.getHeader("Authorization");
if (authHeader == null) {
res.setContentType("application/json;charset=UTF-8");
res.getWriter().write(ExceptionCreator.createJson("Missing Authorization header."));
return;
}
if (!authHeader.startsWith("Bearer ")) {
res.setContentType("application/json;charset=UTF-8");
res.getWriter().write(ExceptionCreator.createJson("Invalid Authorization header."));
return;
}
final String token = authHeader.substring(7);
try {
final Claims claims = Jwts.parser().setSigningKey("secretkey")
.parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
}
catch (Exception f) {
res.setContentType("application/json;charset=UTF-8");
res.getWriter().write(ExceptionCreator.createJson("Invalid token."));
return;
}
chain.doFilter(req, res);
}
}
In general, wrapping the response and then modifying the response output stream after the call to doFilter is the correct approach, e.g.
PrintWriter out = response.getWriter();
CharResponseWrapper wrapper = new CharResponseWrapper(
(HttpServletResponse)response);
chain.doFilter(request, wrapper);
CharArrayWriter caw = new CharArrayWriter();
caw.write("your json");
response.setContentLength(caw.toString().getBytes().length);
out.write(caw.toString());
out.close();
Taken from Oracle JavaEE 5 Tutorial
Nevertheless, your usecase seems more appropriate for being dealt with in a RestController handler method, possibly in conjunction with an #ExceptionHandler(ServletException.class) annotated method. This would be a more generic approach that allows you to harness the power of Spring's content negotiation to deal with the JSON serialization.
I am getting an error trying to move a DataSourceResult from one web service to another... the client calls web service A which resides on our web server. We then make a call to web service B which resides on our db server. The intent is that web service A adds certain sensitive data to the call, that we want hidden behind our firewall... then the call gets handled by web service B, gets a DataSourceResult, and seems to serialize it just fine... note I am using the same set of serilization properties to bot serialize and deserialize, I am just not showing the call to serilize here for brevity. When I go to deserialize this, I get a System.AggregateException - thrown on line "return formatter.ReadFromStreamAsync(typeof(T), stream, null, null).Result as T;" of my deserialization code... any ideas? anything would be much appreciated :)
Serilize code:
string Serialize<T>(MediaTypeFormatter formatter, T value)
{
// Create a dummy HTTP Content.
Stream stream = new MemoryStream();
var content = new StreamContent(stream);
/// Serialize the object.
formatter.WriteToStreamAsync(typeof(T), value, stream, content, null).Wait();
// Read the serialized string.
stream.Position = 0;
return content.ReadAsStringAsync().Result;
}
Deserialize code:
T Deserialize<T>(MediaTypeFormatter formatter, string str) where T : class
{
// Write the serialized string to a memory stream.
Stream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(str);
writer.Flush();
stream.Position = 0;
// Deserialize to an object of type T
return formatter.ReadFromStreamAsync(typeof(T), stream, null, null).Result as T;
}
Json Object / settings being passed into methods:
var json = GlobalConfiguration.Configuration.Formatters.OfType<System.Net.Http.Formatting.JsonMediaTypeFormatter>().FirstOrDefault();
json.SerializerSettings.Formatting = Formatting.None;
json.SerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
json.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
json.SerializerSettings.NullValueHandling = NullValueHandling.Include;
json.UseDataContractJsonSerializer = false;
DataSourceResult result = Deserialize<DataSourceResult>(json, loansJson);
I have this string I try to deserialize and it throws this
error:
`System.AggregateException was unhandled by user code
HResult=-2146233088
Message=One or more errors occurred.
Source=mscorlib
StackTrace:
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at Cavatica35.Web.Api.Controllers.RelationshipsGridController.Deserialize[T](MediaTypeFormatter formatter, String str) in c:\dev\Cavatica35\Code\MarginMaximizerInteractive\Cavatica35.Web\Api\Controllers\RelationshipsGridController.cs:line 54
at Cavatica35.Web.Api.Controllers.RelationshipsGridController.Get(RelationshipDataSourceRequest request) in c:\dev\Cavatica35\Code\MarginMaximizerInteractive\Cavatica35.Web\Api\Controllers\RelationshipsGridController.cs:line 96
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
InnerException: Newtonsoft.Json.JsonSerializationException
HResult=-2146233088
System.AggregateException was unhandled by user code
HResult=-2146233088
Message=One or more errors occurred.
Source=mscorlib
StackTrace:
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at Cavatica35.Web.Api.Controllers.RelationshipsGridController.Deserialize[T](MediaTypeFormatter formatter, String str) in c:\dev\Cavatica35\Code\MarginMaximizerInteractive\Cavatica35.Web\Api\Controllers\RelationshipsGridController.cs:line 54
at Cavatica35.Web.Api.Controllers.RelationshipsGridController.Get(RelationshipDataSourceRequest request) in c:\dev\Cavatica35\Code\MarginMaximizerInteractive\Cavatica35.Web\Api\Controllers\RelationshipsGridController.cs:line 96
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
InnerException: Newtonsoft.Json.JsonSerializationException
HResult=-2146233088
Message=Error converting value "{"$id":"1","Data":[{"$id":"2","Relationship_loanOfficerName":"Deva MMi Admin","guidID":"c4327c4a-7aa5-4503-b738-59a9241a5a1c","name":"New Deva","briefDescription":null,"fullDescription":"","autoRenewLOC":0,"numOfLoans":1,"loanBalance":1000000.0,"numOfDeposits":0,"Relationship_depositbalance":0.0,"numOfOtherRels":0,"otherRelBalance":0.0,"targetROE":0.0,"yearsRemaining":5,"ownedBy":"21973a46-c06e-4ddc-8a94-05bb53c949e6","modBy":"00000000-0000-0000-0000-000000000000","createdBy":"00000000-0000-0000-0000-000000000000","modDate":"12/18/2014","createdDate":"1/1/0001","Relationship_netincome":16955.0,"Relationship_relationshiproe":26.48,"Relationship_avgbalance":1000000.0,"monthsUntilFirstRenewal":"1/1/0001","requiresReview":false,"deleted":false,"extIDList":"","overrideOfficer":false,"selected":false,"ni":16954.908394431,"niOverROE":64028.495587965743,"tag":""}],"Total":1,"AggregateResults":[{"$id":"3","Value":1,"Member":"name","FormattedValue":1,"ItemCount":0,"Caption":null,"FunctionName":"Count_name_28477829","AggregateMethodName":"Count"},{"$id":"4","Value":16955.0,"Member":"Relationship_netincome","FormattedValue":16955.0,"ItemCount":0,"Caption":null,"FunctionName":"Sum_Relationship_netincome_244267","AggregateMethodName":"Sum"},{"$id":"5","Value":26.48,"Member":"Relationship_relationshiproe","FormattedValue":26.48,"ItemCount":0,"Caption":null,"FunctionName":"Sum_Relationship_relationshiproe_8060817","AggregateMethodName":"Sum"},{"$id":"6","Value":1000000.0,"Member":"Relationship_avgbalance","FormattedValue":1000000.0,"ItemCount":0,"Caption":null,"FunctionName":"Sum_Relationship_avgbalance_64680392","AggregateMethodName":"Sum"},{"$id":"7","Value":1,"Member":"numOfLoans","FormattedValue":1,"ItemCount":0,"Caption":null,"FunctionName":"Sum_numOfLoans_54078176","AggregateMethodName":"Sum"},{"$id":"8","Value":1000000.0,"Member":"loanBalance","FormattedValue":1000000.0,"ItemCount":0,"Caption":null,"FunctionName":"Sum_loanBalance_39749352","AggregateMethodName":"Sum"},{"$id":"9","Value":0,"Member":"numOfDeposits","FormattedValue":0,"ItemCount":0,"Caption":null,"FunctionName":"Sum_numOfDeposits_36660208","AggregateMethodName":"Sum"},{"$id":"10","Value":0.0,"Member":"Relationship_depositbalance","FormattedValue":0.0,"ItemCount":0,"Caption":null,"FunctionName":"Sum_Relationship_depositbalance_1827337","AggregateMethodName":"Sum"},{"$id":"11","Value":16954.908394431,"Member":"ni","FormattedValue":16954.908394431,"ItemCount":0,"Caption":null,"FunctionName":"Sum_ni_60302147","AggregateMethodName":"Sum"},{"$id":"12","Value":64028.495587965743,"Member":"niOverROE","FormattedValue":64028.495587965743,"ItemCount":0,"Caption":null,"FunctionName":"Sum_niOverROE_43813805","AggregateMethodName":"Sum"}],"Errors":null}" to type 'Kendo.Mvc.UI.DataSourceResult'. Path '', line 1, position 3087.
Source=Newtonsoft.Json
StackTrace:
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, Encoding effectiveEncoding, IFormatterLogger formatterLogger)
at System.Net.Http.Formatting.JsonMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, Encoding effectiveEncoding, IFormatterLogger formatterLogger)
at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
InnerException: System.ArgumentException
HResult=-2147024809
Message=Could not cast or convert from System.String to Kendo.Mvc.UI.DataSourceResult.
Source=Newtonsoft.Json
StackTrace:
at Newtonsoft.Json.Utilities.ConvertUtils.EnsureTypeAssignable(Object value, Type initialType, Type targetType)
at Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast(Object initialValue, CultureInfo culture, Type targetType)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
InnerException: `
I'm trying to use async actions in MonoRail but when the view is rendered I get an NullReference exception, also tested with emtpy view file.
I also tried to call RenderView("uploadTags.vm") in EndUploadTags.
When I call RenderText(s) in EndUploadTags I don't get the exception.
Stacktrace:
[NullReferenceException: Object reference not set to an instance of an object.]
Castle.MonoRail.Framework.Services.DefaultCacheProvider.Get(String key) +163
Castle.MonoRail.Framework.Views.NVelocity.CustomResourceManager.GetResource(String resourceName, ResourceType resourceType, String encoding) +68
NVelocity.Runtime.RuntimeInstance.GetTemplate(String name, String encoding) +57
NVelocity.Runtime.RuntimeInstance.GetTemplate(String name) +82
NVelocity.App.VelocityEngine.GetTemplate(String name) +47
Castle.MonoRail.Framework.Views.NVelocity.NVelocityViewEngine.Process(String viewName, TextWriter output, IEngineContext context, IController controller, IControllerContext controllerContext) +564
Castle.MonoRail.Framework.Services.DefaultViewEngineManager.Process(String templateName, TextWriter output, IEngineContext context, IController controller, IControllerContext controllerContext) +237
Castle.MonoRail.Framework.Controller.ProcessView() +146
Castle.MonoRail.Framework.Controller.EndProcess() +1579
Castle.MonoRail.Framework.BaseAsyncHttpHandler.EndProcessRequest(IAsyncResult result) +141
[MonoRailException: Error processing MonoRail request. Action uploadtags on asyncController vendor]
Castle.MonoRail.Framework.BaseAsyncHttpHandler.EndProcessRequest(IAsyncResult result) +461
System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +86
This is my test code:
private Output output;
public delegate string Output();
private string DoNothing()
{
return "nothing";
}
private string Upload()
{
return "upload";
}
public IAsyncResult BeginUploadTags(HttpPostedFile xmlFile, Boolean doUpload)
{
if (IsPost)
{
output = Upload;
return output.BeginInvoke(ControllerContext.Async.Callback, null);
}
output = DoNothing;
return output.BeginInvoke(ControllerContext.Async.Callback, null);
}
public void EndUploadTags()
{
var s = output.EndInvoke(ControllerContext.Async.Result);
PropertyBag["logging"] = s;
}
This is a bug in old versions of MonoRail. It works in MonoRail 2.1 RC, but not in an old version I just tried, I got the same null ref exception.
This is what revision 5688 looked like in Subversion, which is where the NullReferenceException is coming from. The code no longer uses the HttpContext for the cache.
public object Get(String key)
{
if (logger.IsDebugEnabled)
{
logger.DebugFormat("Getting entry with key {0}", key);
}
return GetCurrentContext().Cache.Get(key);
}
private static HttpContext GetCurrentContext()
{
return HttpContext.Current;
}
I am facing a strange issue which happens in some cases but not in regular scenario.
I have an ajax call which sends some data to my controller. In majority cases, the ajax call posts data to controller correctly but the case where it fails (exception) I get a log that the json received is incomplete. I don't really know what is the root cause of this erroneous behaviour. Any pointers would be of great help...
Here is my code -
C#
public class MyController : System.Web.Mvc.Controller {
....
....
public JsonResult doPost(string x, string y, int z) {
private JavaScriptSerializer _serialiser = new JavaScriptSerializer();
List<Dictionary<string, object>> items = _serialiser.Deserialize<List<Dictionary<string, object>>>(x);
// deserialsation throws argument exception
...
// do stuff after that...
}
...
}
Exception details
type - System.ArgumentException
message - Unterminated string passed in.
stack trace -
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeString()
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32 depth)
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)
at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)
at System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ValueProviderFactoryCollection.<>c__DisplayClassc.<GetValueProvider>b__7(ValueProviderFactory factory)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ControllerBase.get_ValueProvider()
at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
at System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
Javascript
// A - is a big object
var jsonData = { x: JSON.stringify(A),
y: new Date().toString(),
z: A.Index
};
$.ajax ({
url : '/my/doPost',
type: 'POST', contentType: 'application/json; charset=utf-8;',
cache: false,
data: JSON.stringify(jsonData),
dataType: 'json',
async: true,
success: function () {
// do something on success
},
error: function (jqXhr, textStatus, errorThrown) {
// do something on error
}
});
Thanks
Saarthak