WCF method not accepting POST - wcf

I've spent many hours reading forms all over. Nothing seems to be working. I have a simple ajax enabled WCF service. I can call the Read method and it works find, posting is the problem.
Here is my web.config:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="CompanyNotificationService.NotificationManager.MessagesAspNetAjaxBehavior">
<webHttp defaultOutgoingResponseFormat="Json"/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="CompanyNotificationService.NotificationManager.Messages">
<endpoint address="" behaviorConfiguration="CompanyNotificationService.NotificationManager.MessagesAspNetAjaxBehavior"
binding="webHttpBinding" contract="CompanyNotificationService.NotificationManager.Messages" bindingConfiguration="defaultRestJson" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="defaultRestJson" crossDomainScriptAccessEnabled="false">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="64" maxNameTableCharCount="2147483647" />
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
And my service
[ServiceContract(Namespace = "NotificationManager.Messages")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults = true)]
public class Messages
{
[OperationContract, WebGet(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
public List<Message> Read()
{
Notifications notifications = Notifications.Get();
return notifications.Messages;
}
[OperationContract, WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
public void Create(Message models)
{
var i = 1; //I break here, just to inspect everything...not finished
}
[DataContract]
public class Message : IMessage
{
[DataMember]
public string ID { get; set; }
[DataMember]
public string Text { get; set; }
[DataMember]
public DateTime StartDate { get; set; }
[DataMember]
public DateTime ResumeDate { get; set; }
[DataMember]
public string CreatedUser { get; set; }
}
And fiddler info
POST http://localhost:64394/NotificationManager/Messages.svc/Create HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/json
X-Requested-With: XMLHttpRequest
Referer: http://localhost:64394/NotificationManager/Manage.aspx
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost:64394
Content-Length: 1130
DNT: 1
Connection: Keep-Alive
Pragma: no-cache
Cookie: __AntiXsrfToken=82ba422caa20485690cc905fe6a4b022
HTTP/1.1 400 Bad Request
And finally the exception
The server encountered an error processing the request.
The exception message is 'The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation 'Create'. Encountered unexpected character 'm'.'. See server logs for more details.
The exception stack trace is:
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest(Message message, Object[] parameters) .....
oh, I almost for got the json from fiddler
models=[{"ID":"1","Text":"here is my message","StartDate":"2013-12-07T06:54:34.396Z","ResumeDate":"2013-12-07T06:54:34.396Z","CreatedUser":"charbaugh"}]
Any help would be great! I never posted here an I am always able to find my answers fast, but this has me wrecked!

Sure, exception is because WCF service is expecting a JSON object which begins with a {, but your body begins with m as in models=.... This is incorrect.
For your request, correct JSON to send to the service is:
{"models": {"ID":"1","Text":"here is my message","StartDate":"/Date(1320825600000-0800)/","ResumeDate":"/Date(1320825600000-0800)/","CreatedUser":"charbaugh"}}
Also, note that I have changed the datetime contents/format. For more information, see: How do I format a Microsoft JSON date?

The problem might be on a client side. I see you use ajax to call your service. I saw that there might be issues when you pass an object to ajax request, try to pass it as a string.
data: '[{"ID":"1","Text":"here is my message","StartDate":"2013-12-07T06:54:34.396Z","ResumeDate":"2013-12-07T06:54:34.396Z","CreatedUser":"charbaugh"}]'
More info here: http://encosia.com/asmx-scriptservice-mistake-invalid-json-primitive/

Related

How to configure WCF services

I'm new to using WCF services and i hope you can help me out on some problems invoking an external REST webservice. I have create two applications to try and test my service.
Console application to test my class lib
An umbraco application which hosts my services
Both localhost.
Here is the code of my service:
namespace HorecaWebservices.Webservices
{
[ServiceContract]
public interface IWS_Test
{
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
Agenda GetAgenda(String mobileAppKey);
}
}
namespace HorecaWebservices.Webservices
{
public class WS_Test : IWS_Test
{
public Agenda GetAgenda(String mobileAppKey)
{
return BL_Agenda.GetAgenda(mobileAppKey);
}
}
}
Web config of my service:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true"
automaticFormatSelectionEnabled="true"
defaultOutgoingResponseFormat="Json">
</standardEndpoint>
</webHttpEndpoint>
</standardEndpoints>
<services>
<service name="HorecaWebservices.Webservices.WS_Test"
behaviorConfiguration="MyServiceTypeBehaviors">
<endpoint address="" binding="wsHttpBinding"
contract="HorecaWebservices.Webservices.IWS_Test"/>
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding" address="mex"/>
</service>
</services>
</system.serviceModel>
Here is the code from my console application which invokes the service method:
public static class BL_Agenda
{
public static Agenda GetAgenda()
{
Agenda agenda = new Agenda();
WebRequest request = WebRequest.Create("http://localhost:63462/Webservices/WS_Test.svc/GetAgenda");
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
string postData = "{\"mobileAppKey\":\"HEMDZ\"}"; //encode your data
using (Stream s = request.GetRequestStream())
{
using (StreamWriter sw = new StreamWriter(s))
sw.Write(postData);
s.Close();
}
try
{
using (Stream s = request.GetResponse().GetResponseStream())
{
using (StreamReader sr = new StreamReader(s))
{
var jsonData = sr.ReadToEnd();
agenda = JsonConvert.DeserializeObject<Agenda>(jsonData);
}
s.Close();
}
}
catch (WebException e)
{
agenda = null;
WebExceptionStatus status = e.Status;
Console.WriteLine(status.ToString());
}
return agenda;
}
Now whenever i run this code the request.GetResponse() throws a System.Net.WebException "(415) Cannot process the message because the content type 'application/json; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'"
After a couple of hours trying to find out what the problem is i still cant figure it out.. Can someone help me out on this?
At a first glance your endpoint uses the wrong binding (wsHttpBinding):
<endpoint address="" binding="wsHttpBinding" contract="HorecaWebservices.Webservices.IWS_Test"/>
Whereas it should be webHttpBinding:
<endpoint address="" binding="webHttpBinding" contract="HorecaWebservices.Webservices.IWS_Test"/>
For a complete webHttp-sample binding take a look at this article: http://weblogs.asp.net/kiyoshi/archive/2008/10/08/wcf-using-webhttpbinding-for-rest-services.aspx
When changing the binding other issues are likely to occur. One thing is, that you'll probably don't need the <standardEndpoints>-node any more. So I'd suggest staying close to the linked sample.
Additionally it's always a good idea to activate tracing. Having tracing activated you'll get more detailed information about your 500 error (and probably others too).
This example is not exactly the same, but maybe the Factory attribute suggested will give you some clues.
HTTP/1.1 415 Cannot process the message because the content type 'application/json; charset=utf-8' was not the expected type 'text/xml; charset=utf-8'
I've got it! I finally sorted out the bad request error. I had to replace the BodyStyle = WebMessageBodyStyle.Bare setting to BodyStyle = WebMessageBodyStyle.WrappedRequest.
Thnx for all the help guys!

How to get response with SOAPAction in WCF 4.0 Service method?

I have a web service method which can return below response without (SOAPAction: "")
Method
public string SyncData(Stream xml)
{
}
web.config
<service behaviorConfiguration="" name="PRO.API">
<endpoint address="" behaviorConfiguration="web" binding="customBinding"
bindingConfiguration="RawReceiveCapable" contract="PRO.IAPI" />
</service>
customBinding
<customBinding>
<binding name="RawReceiveCapable">
<webMessageEncoding webContentTypeMapperType="PRO.RawContentTypeMapper, PRO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<httpTransport manualAddressing="true" maxReceivedMessageSize="524288000" transferMode="Streamed" />
</binding>
</customBinding>
public class RawContentTypeMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
if (contentType.Contains("text/xml")
|| contentType.Contains("application/xml")
|| contentType.Contains("text/html"))
{
return WebContentFormat.Raw;
}
else
{
return WebContentFormat.Default;
}
}
}
Required Response with SOAPAction: ""
Content-Type: text/xml;charset=utf-8
Content-Length: 346
SOAPAction: ""
<soapenv:Envelope" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<syncOrderRelationResponse xmlns="http://www.csapi.org/schema/parlayx/data/sync/v1_0/local">
<result>0</result>
<resultDescription>success</resultDescription>
</syncOrderRelationResponse>
</soapenv:Body>
</soapenv:Envelope>
What should I do to get response with SOAPAction, thanks in adavnce?
please see this link for "Sample SOAP response"
http://support.sas.com/documentation/cdl/en/wbsvcdg/62759/HTML/default/viewer.htm#n1wblekhip1yrln1fv2s5b6a2d9f.htm
You can specify Action property in OperationContract attribute. Check this question How to specify custom SoapAction for WCF

Getting null values in post wcf service

I am writing a WCF service. Here is Service side implementation
[OperationContract(Name="GetMediaFile")]
[Description(ServiceDescConstants.GetMediaFile)]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = UriTemplateConstants.GetMediaFile)]
Stream GetMediaFile(string type, string mediaId);
where
UriTemplateConstants.GetMediaFile = "GetMediaFile?type={type}&mediaId={mediaId}";
Here is interface method implementation
public Stream GetMediaFile(string type, string mediaId)
{
CustomerBL customerBl = new CustomerBL();
return customerBl.getMediaFile(Convert.ToInt32(type), Convert.ToInt32(mediaId));
}
On client side I am using RestClient plugin for testing service.
Here is data I am sending
URL : customersite/GetMediaFile
Header : Content-Type = x-www-form-urlencoded
Body : type=0&mediaId=1
Any help !!
Now the PROBLEM is that I am getting null values
Modify the interface method:
[OperationContract(Name = "GetMediaFile")]
[Description(ServiceDescConstants.GetMediaFile)]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "/GetMediaFile")]
Stream GetMediaFile(Stream input);
And also modify it's implementation:
public Stream GetMediaFile(Stream input)
{
StreamReader sr = new StreamReader(input);
string s = sr.ReadToEnd();
sr.Dispose();
NameValueCollection qs = HttpUtility.ParseQueryString(s);
string type = qs["type"];
string mediaId = qs["mediaId"];
CustomerBL customerBl = new CustomerBL();
return customerBl.getMediaFile(Convert.ToInt32(type), Convert.ToInt32(mediaId));
}
In the web.config, use the following configuration (make sure that you use your own namespaces / classes / interfaces names):
<system.serviceModel>
<services>
<service name="WcfServices.MyService">
<endpoint address=""
name="webEndPoint"
behaviorConfiguration="webBehavior"
binding="webHttpBinding"
contract="WcfServices.IMyService" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
This is a sample request:
POST /MyService.svc/GetMediaFile HTTP/1.1
Host: localhost:64531
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
type=0&mediaId=1
The solution is an adaptation of Edgardo Rossetto's blog article, Raw HTTP POST with WCF.

Large video stream/download incomplete through WCF streaming, no errors

I am currently fixing a WCF based server enabled to provide large (multiple gigabytes) mpeg video files for a client.
The client shall both save the video and view it while still downloading. A buffered service failed because the video was loaded into memory completely.
When I try to get it with wget.exe or a web browser, it loads only a part (roughly 600 to 800 MB), then it stops without an error, neither on the client nor on the server side.
When opening the video stream in Internet Explorer, no time slider appears on the bottom, and the HTTP response has no content-length in header.
The HTTP response contains no Content-Length in headers, although it has been set in the code (see below).
Does anybody know how to fix this problem, or an alternate way?
Contract interface of the service:
[ServiceContract(Namespace = "http://www.blah.com/MyFunnyVideos")]
public interface IMyFunnyVideosService
{
[OperationContract(Name = "GetVideo")]
[WebGet(UriTemplate = "LORESVIDEO/{videoId}", ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare)]
Stream GetVideo(string videoId);
}
Implementation:
[ServiceBehavior(Namespace = "http://www.blah.com/MyFunnyVideos", InstanceContextMode = InstanceContextMode.PerCall)]
public class MyFunnyVideosService : IMyFunnyVideosService
{
// ...
Stream IMyFunnyVideosService.GetVideo(string videoIdString)
{
Logger.LogMethod();
try
{
FileStream fstream = GetVideoFileStream(int.Parse(videoIdString));
fstream.OpenRead();
var response = WebOperationContext.Current.OutgoingResponse;
response.ContentLength = fstream.Length;
return fstream;
// ...
}
Web service config contains:
<webHttpBinding>
<binding name="restBinding" transferMode="StreamedResponse" maxBufferSize="21474836470" maxReceivedMessageSize="21474836470" />
</webHttpBinding>
<behaviors>
<endpointBehaviors>
<behavior name="[omitted]">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
HTTP response headers:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: video/mpeg
Server: Microsoft-HTTPAPI/2.0
Date: Thu, 30 Jan 2013 15:52:04 GMT
Got to answer my own question:
It was simply a timeout. Default sendTimeout in webHttpBinding is 1 minute, then the transmission stops without any error.
So, I only had to set sendTimeout="00:10:00" in the webHttpBinding, for a 10min timeout.

consuming wcf service application from JQuery Ajax

i've built a WCF web application , exposed it's method into get enabled methods
[OperationContract]
[WebGet]
string getStatistics();
[OperationContract]
[WebGet]
string getVenues(string BrandName, int limit);
and edited the config file :
<endpoint address="json" binding="webHttpBinding" contract="foursquare2RDF.IVenue2rdf" behaviorConfiguration="restBehavior"/>
and in the service behavior :
<endpointBehaviors>
<behavior name="restBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
i hosted the service on the IIS , and it works very fine from the browser so when u hit :
http://localhost:83/venue2rdf.svc/json/getStatistics
it returns a good results
the problem is i can't consume this restful service from if shows those errors :
OPTIONS http://localhost:83/venue2rdf.svc/json/getStatistics?{'venues':'100'} 405 (Method Not Allowed)
XMLHttpRequest cannot load [http://localhost:83/venue2rdf.svc/json/getStatistics][1]. Origin null is not allowed by Access-Control-Allow-Origin.
i'm using that code to call the service :
$.ajax({
type: "get",
url: statisticsURL,
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
eval("var x = " + msg.d);
console.log(x);
}
});
what ive reached so far :
i tried replacing $.ajax with $.getjson like stated in similar question
and the error 405 was removed , the second error just appears
i've found something called Ajax enabled WCF service project , but still i don't want to migrate in to a new project
i know there are similar questions but all don't fit , showing different errors that mine
You should probably make it a JSONP request since your going cross domain, you running into the same origin policy:
$.getJSON(stastatisticsURL + "?callback=?", success: function (msg) {
eval("var x = " + msg.d);
console.log(x);
});
the ?callback=? part tels jquery to make it JSONP. I advise you to read up on what JSONP is since it isn't a silver bullet. To enable JSONP on WCF services read:
C# WCF Web API + JSONP
For you to consume a cross domain WCF REST service using jQuery please find a sample below:
My Service looks as below:
[ServiceContract]
public interface IJSONPService
{
[OperationContract]
[WebGet]
string GetDate();
[OperationContract]
[WebInvoke]
string PostData(string name);
}
Now my config entries for the above service looks as shown:
<services>
<service name="Service.JSONPService">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="json" bindingConfiguration="defaultRestJsonp" contract="Service.IJSONPService">
</endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="json">
<enableWebScript />
</behavior>
</behaviors>
</endpointBehaviors>
<webHttpBinding>
<binding name="defaultRestJsonp" crossDomainScriptAccessEnabled="true">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="64" maxNameTableCharCount="2147483647" />
<security mode="None" />
</binding>
</webHttpBinding>
You need to note the crossDomainScriptAccessEnabled attribute in the binding element "defaultRestJsonp" which takes care of determining the request to be for JSONP and appropriately converting the response to be wrapped in the callback method from the URL which comes as a query string
Now from your page do the below JavaScript that calls the above WCF REST service as shown:
function TestingWCFRestWithJsonp() {
$.ajax({
url: "http://domain.com/Service/JSONPService.svc/GetDate",
dataType: "jsonp",
type: "GET",
timeout: 10000,
jsonpCallback: "MyCallback",
success: function (data, textStatus, jqXHR) {
alert(data);
},
error: function (jqXHR, textStatus, errorThrown) {alert('error');
},
complete: function (jqXHR, textStatus) {alert('complete');
}
});
}
function MyCallback(data) {
alert(data);
}
Check out the jsonpCallback property in the $.ajax method call.
The raw request to the web service call looks as below:
GET http://localhost/Service/JSONPService.svc/GetDate?callback=MyCallback&_=1343391683779 HTTP/1.1
Host: localhost
Connection: keep-alive
And the raw response from the WCF REST service looks as below:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/x-javascript
Date: Fri, 27 Jul 2012 12:21:23 GMT
Content-Length: 27
MyCallback("27\/07\/2012");
NOTE: When you perform a JSONP request your $.ajax methods error/complete/success are not called.