RESTful WCF Service Fails When Large JSON POSTed - json

I'm writing a web application that calls a WCF RESTful interface. One of my service methods takes a string of JSON as a parameter. Calls to that method work great as long as the JSON string is under a specific length. As soon as the string exceeds that length, the service returns a 404 error. I've been looking for an answer to this and tried a couple of different ideas to address this, but the error persists.
The client-side code is:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serviceUri + parameters);
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
The contract for the service method is:
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "MethodName?stages={stages}&providerID={providerID}")]
string MethodName(string stages, int providerId);
The stages parameter above is the one that receives the long string of JSON.
I also added the following to the web.config file of the service:
<bindings>
<basicHttpBinding>
<binding name="basichttpbinding_esynchrony"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
</binding>
</basicHttpBinding>
</bindings>
If anyone can help with an answer or even a link to an article that explains how to solve this particular issue, it would be very much appreciated.

First, I noticed that you have created an Http-POST request to the service while you specify that the operation is GET, could it work well? In my opinion, the service contract may have another binding, such as Webhttpbinding, with which could publish the WCF service in Restful style. In that cases, the server would accept JSON data, otherwise only SOAP message based on XML is accepted and HTTP verb is always POST.
Moreover, we usually use the following configuration in case the request exceeds the length.
<system.serviceModel>
<services>
<service behaviorConfiguration="mybehavior" name="WcfService1.Service1">
<endpoint address="" binding="webHttpBinding" contract="WcfService1.IService1" behaviorConfiguration="webbev" bindingConfiguration="mybinding"></endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="mybinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" sendTimeout="00:10:00" receiveTimeout="00:10:00">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" />
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="mybehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webbev">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
Feel free to let me know if there is anything I can help with.

Related

Cannot Read JSON request body parameters in wso2 ESB as an api

I have created an API in the WSO2 ESB (4.8.1) and I wanted to send a PUT request to that API with a request body. I have tried with the sample
and I wanted to log a property values in the insequence of the defined API.
This is my request body:
This is the way how I tried to log the location name:
But I’m getting an error like this:
(ERROR - SynapseJsonPath #stringValueOf. Error evaluating JSON Path . Returning empty result. Error>>> invalid path)
So how can I read these values?
To achieve your requirement, you should send the "Content-Type" HTTP header with the request like below,
"Content-Type : application/json"
enter image description here
Then you can log the specific JSON element like below.
<log>
<property name="location" expression="json-eval($.coordinates.location[0].name)"></property>
</log>
Then you can see following log,
enter image description here
Thanks.
If you want to get single variable from user in json request you can use this code
Use This json:
{
"namee":"UsmanYaqooooooooooob"
}
Api Code:
<api xmlns="http://ws.apache.org/ns/synapse" name="Hello" context="/hello">
<resource methods="POST" uri-template="/post">
<inSequence>
<log level="custom">
<property name="===========inSequence" value="****"></property>
<property name="locationsssssssss" expression="json-eval(.namee)"></property>
</log>
<payloadFactory media-type="json">
<format>{"hello":"world"}</format>
<args></args>
</payloadFactory>
<property name="messageType" value="text/xml"></property>
<respond></respond>
</inSequence>
</resource>
</api>

Extract fields from JSON response in Mule

I have a JSON response which is like {"id":10,"name":"ABCD","deptId":0,"address":null}
I need to split this JSON and extract the id to pass on to another service.
My mule xml is as below
<jersey:resources doc:name="REST">
<component class="com.employee.service.EmployeeService"/>
</jersey:resources>
<object-to-string-transformer doc:name="Object to String"/>
<logger message="Employee Response #[payload]" level="INFO" doc:name="Logger"/>
<set-payload value="#[payload]" doc:name="Set Payload" />
<json:object-to-json-transformer doc:name="Convert String to JSON" />
<logger message="JSON Response #[payload]" level="INFO" doc:name="Logger"/>
<json:json-to-object-transformer returnClass="java.util.Map" />
<expression-transformer expression="#[payload]" />
<collection-splitter />
When I run this I get the error
Object "java.util.LinkedHashMap" not of correct type. It must be of type "{interface java.lang.Iterable,interface java.util.Iterator,interface org.mule.routing.MessageSequence,interface java.util.Collection}" (java.lang.IllegalArgumentException). Message payload is of type: LinkedHashMap
How can I fix this error?
Thanks
I was able to get this done by writing a custom converter
remove your last four lines of code. set logger #[payload.id] in flowvars and access it
I believe the error you are getting is already on this part, <collection-splitter />. Have you debugged this already?
Not sure what the splitter is for but you can simply do #[payload.id] to get id once you have a HashMap type of payload.
The JSon module as well has the ability to use jsonpath in expressions, such as:
#[json:/id]

WCF WebFaultException ExceptionDetail

I'm creating a WCF service that returns data in JSON Format. I'm trying to figure out how to best handle exceptions and I'm trying to use the WebFaultException class to return an exception detail message in the response, which can later be outputted to the user.
A simple Test of this method I am trying is as follows
The WCF Service method
<WebInvoke(Method:="POST",
ResponseFormat:=WebMessageFormat.Json)>
<OperationContract()>
Public Function Test() As Object
Throw New WebFaultException(Of String)("Message Details", Net.HttpStatusCode.NotFound)
End Function
From what I found searching for answers to this questions, you should give the service a behaviorconfiguartion which sets includeExceptionDetailInFaults to true.
My Web.Config
<service name="WebserviceExceptionTest.Service" behaviorConfiguration="behavior">
<endpoint address="" behaviorConfiguration="WebserviceExceptionTest.ServiceAspNetAjaxBehavior"
binding="webHttpBinding" contract="WebserviceExceptionTest.Service" />
</service>
<serviceBehaviors>
<behavior name="behavior">
<serviceDebug includeExceptionDetailInFaults="True"/>
</behavior>
Unfortunately, this appears to not do the trick for me and the response still does not include the exception detail, the JSON string looks like this:
{"ExceptionDetail":null,"ExceptionType":null,"Message":"Not Found","StackTrace":null}
Does anyone have any idea of what it is I am doing wrong, or am I just entirely on the wrong path? Thanks!
Edit
The Response I'm getting is always "500 Internal server error" Even though I'd expect it to get a 400 not found. The Error message does contain the "No Content" though.
Set your automaticFormatSelectionEnabled to be false, defaultOutgoingResponseFormat to Json (I believe it even ignores ResponseFormat:=WebMessageFormat.Json)
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="false" defaultOutgoingResponseFormat ="Json" />
http://msdn.microsoft.com/en-us/library/system.servicemodel.description.webhttpendpoint.automaticformatselectionenabled.aspx

Restful WCF POST issue with application/json content type request

I've configured a RESTful WCF with the following POST "operation":
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/Test", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json)]
void PostTest(Stream stream);
In my web.config, I've configured the following:
<service name="MyTest.TestSvc" behaviorConfiguration="MyTest.TestBehavior" >
<endpoint address="" behaviorConfiguration="MyBehavior" binding="webHttpBinding" contract="MyTest.ITestSvc"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
<endpointBehaviors>
<behavior name="MyBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyTest.TestBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
When I sent a POST message using "text/plain" or "json" everything works fine.
However, when I try to send a POST message with
ContentType = "application/json"
It fails with the following message:
The remote server returned an error: (400) Bad Request
The only solution which I found was to define the Factory class : System.ServiceModel.Activation.WebServiceHostFactory int the Svc definition markup.
I found this solution in the following link:
Send JSON to WCF 3.5 using Ajax
As I understood , defining the WebServiceHostFactory is only useful if you don't want to edit the web.config.
How can I make it work without defining the WebServiceHostFactory?
Notice that I succeed to get "json" content type POST message but not "application/json" content type.
The problem is that to use the raw programming model (using a Stream parameter), you'll need to tell WCF to not try to understand the request as JSON, instead just pass the raw request body to the parameter. You can do that using a WebContentTypeMapper. The post at http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-receiving-arbitrary-data.aspx shows how this can be done. The solution with the factory works because it does that when it creates the endpoint.

Calling WCF services from Javascript with UriTemplate and POST data

I've got a WCF 4.0 service that's currently set up for HTTP GET requests. I'm trying to modify it so that it uses POST, but keep backwards compatibility with the existing GET URIs. The web service is being called with jQuery and JSON data. Therefore, my requirements are the following:
Match the existing GET URI, presumably by using the UriTemplate parameter of the WebInvoke attribute.
Get the existing parameters from JSON data in the POST body, presumably by using WebMessageBodyStyle.Wrapped and WebMessageFormat.Json with the WebInvoke attribute.
Preferably have a way to pull large blobs of a data out of the POST body, probably also wrapped in a JSON object.
Alright, with that out of the way, here's what I've got so far. My little test service is called AjaxService and it's got one method called ToUpper. First, my web.config:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="WebApplication2.AjaxServiceAspNetAjaxBehavior">
<!--<enableWebScript />-->
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<remove scheme="http" />
<add scheme="http" binding="webHttpBinding" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="WebApplication2.AjaxService">
<endpoint address=""
behaviorConfiguration="WebApplication2.AjaxServiceAspNetAjaxBehavior"
binding="webHttpBinding"
contract="WebApplication2.AjaxService" />
</service>
</services>
</system.serviceModel>
</configuration>
The following version of my ToUpper function allows me to pass its argument in the URI just like an HTTP GET.
[OperationContract]
[WebInvoke( UriTemplate="ToUpper?str={str}",
Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
RequestFormat=WebMessageFormat.Json,
ResponseFormat=WebMessageFormat.Json)]
public string ToUpper(string str)
{
return str.ToUpper();
}
It's used in Javascript as follows and correctly returns "THIS IS FROM THE URI".
$(document).ready(function () {
$.ajax({
type: "POST",
url: "AjaxService.svc/ToUpper?str=this%20is%20from%20the%20uri",
contentType: "application/json; charset=utf-8",
success: function (data) {
console.log("result: " + JSON.stringify(data));
},
error: function (jqXHR, textStatus, errorThrown) {
console.log("error", jqXHR, textStatus, errorThrown);
}
});
});
I can put the parameter in the POST data instead of the URI by removing UriTemplate="ToUpper?str={str}" from the WebInvoke parameters and using this javascript instead. It correctly returns "THIS IS FROM THE POST".
$(document).ready(function () {
$.ajax({
type: "POST",
url: "AjaxService.svc/ToUpper",
data: JSON.stringify({str:"This is from the POST"}),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
console.log("result: " + JSON.stringify(data));
},
error: function (jqXHR, textStatus, errorThrown) {
console.log("error", jqXHR, textStatus, errorThrown);
}
});
});
I was hoping that if I left the UriTemplate="ToUpper?str={str}" in place and use the above javascript, it would be smart enough to pull the str parameter out of the POST data instead of the URI. Unfortunately, it just gives me an error 400. Is there a way to make that work?
One other thing I tried is using the optional Stream parameter to get at the raw contents of the POST data. But as this blog post points out, you can only get that stream if you set the content type to plain text instead of JSON. I could do that and manually parse the stream, but I think I'd also need to manually examine the URL to figure out if I got real values or defaults. Yuck.
If there's no way to make this work with the system bindings/settings, I was thinking about trying to write a custom binding that would be smart about pulling parameters out of the POST and URI, and also give you that raw stream even when you're using JSON. I spent a few hours trying to figure out how to do that but I'm stumped!
Has anyone else tackled this one or have any ideas on how to make it work? I can't imagine I'm the first one to have tried doing this, but I've come up empty handed after doing lots of searching.