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
Related
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.
How to handle exception from Rest service "testReportReadUrl" in grid, Currently Grid displaying no records and not showing exception message.
<kendo:dataSource pageSize="20" serverPaging="true"
serverSorting="true" serverFiltering="true" serverGrouping="true">
<kendo:dataSource-transport>
<kendo:dataSource-transport-read url="${testReportReadUrl}"
type="POST" contentType="application/json" />
</kendo:dataSource-transport>
Need to add error ="errorHandler" with data source as below
<kendo:dataSource pageSize="20" serverPaging="true"
serverSorting="true" serverFiltering="true" serverGrouping="true" error="handleError">
<kendo:dataSource-transport>
<kendo:dataSource-transport-read url="${testReportReadUrl}"
type="POST" contentType="application/json" />
</kendo:dataSource-transport>
And provide handler method
function handleError(e){
alert("An error occurred")
}
In Azure API Management, when the response going back to the client is a 500, I wish to check the body of the response to see if it matches "Some text". I need to do this so that I may change the body of the response to contain some more helpful text in this particular scenario.
The following <outbound> section of my policy is accepted by the API Management console, but when I test and get a 500, API Management generates an error -
Expression evaluation failed. Unable to cast object of type 'Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody' to type 'System.String'.
I'm guessing this is my fault, but does anybody know how I can amend the ploicy so that it does not generate an error? To clarify, the error is being generated by this line - ((string)(object)context.Response.Body == "Some text").
<outbound>
<choose>
<when condition="#((context.Response.StatusCode == 500) && ((string)(object)context.Response.Body == "Some text"))">
<set-status code="500" reason="Internal Server Error" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>
{
"statusCode": "500",
"Message": "Some different, more helpful text."
}
</set-body>
</when>
</choose>
</outbound>
Update
I've discovered that context.Response.Body is of type IMessageBody. There seems to be woefully little documentation around this type, and the only reference I can find comes under <set-body> in the Transformation Policies API management documentation.
The troube is, the example that MS havd documented produces an exception when I try and save my policy -
<set-body>
#{
JObject inBody = context.Request.Body.As<JObject>();
if (inBody.attribute == <tag>) {
inBody[0] = 'm';
}
return inBody.ToString();
}
</set-body>
Property or indexer 'string.this[int]' cannot be assigned to -- it is read only
Try context.Request.Body.As<string>(). Method As currently supports following types as generic argument value:
byte[]
string
JToken
JObject
JArray
XNode
XElement
XDocument
Mind that if you try to call .As<JObject> over response that does not contain valid JSON you would get an exception, same applies to other types as well.
My application is interacting with Alfresco workflow by REST.
There is a task having association to an object of type cm:person, its value should be collected form the end user -to be used as assignee of the next task-. How can I set this value by REST ??
I tried to send HTTP "PUT" request (content-type:application/json) on URL
http://localhost:8080/alfresco/service/api/task-instances/activiti$11102
and body request is:
{
"cio_employee": "workspace://SpacesStore/bcb9817f-5778-484b-be16-a388eb18b5ab" }
where "workspace://SpacesStore/bcb9817f-5778-484b-be16-a388eb18b5ab" is the reference of admin person, but when I end the task (by REST also), Alfresco throws error:
...
Caused by: org.activiti.engine.ActivitiException: Unknown property
used in expression: ${cio_employee.properties.userName} ... Caused by:
org.activiti.engine.impl.javax.el.PropertyNotFoundException: Could not
find property properties in class java.lang.String
Below is the task and its model definition:
//User Task:
<userTask id="assignHandler" name="Assign Employee" activiti:assignee="admin"
activiti:formKey="cio:assignEmployeeTask">
<documentation>Please, Assign employee to the next task</documentation>
<extensionElements>
<activiti:taskListener event="complete"
class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
<activiti:field name="script">
<activiti:string>
execution.setVariable('cio_employee',
task.getVariable('cio_employee'));
</activiti:string>
</activiti:field>
</activiti:taskListener>
</extensionElements>
</userTask>
///////////////////////////////////////////////////////////
//Model
...
<types>
...
<type name="cio:assignEmployeeTask">
<parent>bpm:workflowTask</parent>
<mandatory-aspects>
<aspect>cio:employee</aspect>
</mandatory-aspects>
</type>
...
</types>
...
<aspects>
<aspect name="cio:employee">
<associations>
<association name="cio:employee">
<source>
<mandatory>false</mandatory>
<many>false</many>
</source>
<target>
<class>cm:person</class>
<mandatory>true</mandatory>
<many>false</many>
</target>
</association>
</associations>
</aspect>
</aspects>
////////////////////////////////////////////////////////////////////////
After searching deeply, you will need to send POST request on
http://localhost:8080/alfresco/s/api/task/[taskId]/formprocessor
with body:
{
"assoc_cio_employee_added": "workspace://SpacesStore/bcb9817f-5778-484b-be16-a388eb18b5ab"
}
and for removing use the key "assoc_cio_employee_removed"
https://wiki.alfresco.com/wiki/Forms_Developer_Guide
Hope it may help someone.
Alfresco Version 4.2.e
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.