Line breaks with WCF, JSON and a non-Windows client - c#

I have a .NET WCF service using WebMessageFormat.Json as both its ResponseFormat and its RequestFormat. The service runs on a Windows server, the client is an Android tablet.
As it turns out, strings sent from the client to the server contain LF linebreaks ("\n") instead of CRLF("\r\n"). Since Android is Linux-based, this is not surprising. However, the data is stored in a Windows database and read by Windows clients, so I need CRLF line breaks.
Is there a more elegant way to solve this issue than to manually s = s.Replace("\n", "\r\n"); every string received via WCF? Since WCF has so many options and features, I figured that there might be some hidden AutoTranslateNewlines option that I have missed...
Additional information: My service is declared roughly like this:
[OperationContract()]
[WebInvoke(ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json,
UriTemplate = "MyService?UserId={myUserId}")]
public Reply MyService(String myUserId, Request someRequest) { ... }
where Request is a custom class with a few String fields, some of which can contain multiple lines of text.

You mention that you are using
s = s.Replace("\n","\r\n");
But an issue could arise where you have some "\r\n" sequences in your string. These would become "\r\r\n", which would be an issue. To solve this problem, simply do the following instead.
s = s.Replace("\r\n", "\n");
s = s.Replace("\r", "\n");
s = s.Replace("\n", "\r\n");
which should handle all situations, though perhaps not the most performant. For better performance, perhaps you can use a regular expression.

Related

Sending huge amount of data received from slow external web service via stream

I wrote small REST web service using WCF. These web service will be serve as facade to other more specialized webservices.
So it look like:
Java App (client) <-> My Rest WCF Web Service <-> External_Web_Services
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/GetListOfRecordByRootId/{userid}/{rootId}")]
List<RecordDTO> GetListOfRecordByRootId(string userid, string rootId);
But it work in this way:
public List<TimeSeriesDto> GetListOfTimeseriesByDataSetId(string guid, string dataSetId, string numberOfSeries)
{
Var client = this.OpenToExternalWebservice();
return client.GetDataByRootId.ToList();
}
Where OpenToExternalWebservice open connection to web service. But I meet one serious problem -> amount of data.
It turn out that external webservice are quite slow and limited. Alone result are huge. - I received more then 200MB of result.
Question: Is it possible to return data via stream at chuncked way?
Let’s present you small example:
DataAtRoot have 100 000 records;
Step 1) I download first 1000 records from external web service
Step 2)After receive it I convert them to: List. Then I will pack it to json usign DataContactJsonSerializer.
Step 3)After convert them to Json I wamt to send it via stream but I DONT want to close connection.
Step 4) Remove old 1000records which I sended.
Step 5) Back to step 1 (get next 1000records)
So my dream is sending many list of record via stream:
ONE STREAM where I will put after receiving next part of data:
List<Record> Row Number 0-999
List<Record> Row Number 1000-1999
List<Record> Row Number 2000-2999
List<Record> Row Number 3000-3999
…
Is it possible? Or maybe do you have another solution??
Please help me. Thank you in advantage for any answer

POST method, error 400l bad request. asp.net

I'm trying to send data from my iPhone to a windows server 2008.
I found a tutorial, but I'm unfamiliar with asp.net.
So this is my code (in asp.net)
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "InsertEmployee?names={name}&lastnames={lastname}",
BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
//ResponseFormat = WebMessageFormat.Xml)]
//method
bool InsertEmployeeMethod(string name, string lastname);
//
and, I tried testing the installation with "postman", software that let me see the errors and checks in the Method. I sent a test of the code via postman.
And in Google, like this:
http://192.168.1.209/JsonWcfService/GetEmployees.svc/InsertEmployee?name=ildaguin&lastname=pregunton
That returns an Error 400 (Bad request).
How do I resolve this?
One way 400 Bad Request occurs is a syntax error. More details would be helpful including the message you are sending with Postman and the error returned if an error is returned.
If an error is not returned in Postman, then I would compare that to the message right before it is being sent in debug from your code. I can help you out with both if you can post additional details / code.
It is likely that you are missing some information or there is some spelling issue in the request, is a header variable required perhaps ( maybe Bearer token ). Are some words not case correct?
Good Luck

WCF HTTP GET parameter causes bad request

I have a WCF service with the following operation contract:
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "/VerifyKeys.json/{customerKey}/{userKey}")]
[return: MessageParameter(Name = "MyDetail")]
MyDetail VerifyKeys(string customerKey, string userKey);
My method is like this:
public MyDetail VerifyKeys(string customerKey, string userKey)
{
...
return _myDetail;
}
My request is like this:
http://mydomain.com/MyService.svc/web/VerifyKeys.json/FE3D0F1D-5B8B-4677-B332-70B7ABA80A97/08F4349A-30E5-457D-F2BD-70A23CE17F41?deviceId=66345ec6-a5fe-4b5f-8cf2-1b0d8c344dc2&deviceToken=AgTGERCBaS3d8n2QWxF9EtwcLktIoygoXpc8Y42ObZWja3RSjN%2bFBeshaY4ASainj3MusBbVopXbUFQrrgXUOSkAbOA7tChNKOFNKQ2gB8sEfCe5Du9BZufW4bAP5312MKRqV8g%3d&deviceType=Pink24
I have different versions of my application calling this method. Rather than create a new method, I have used a query string at the end. By parsing the url, I can get the additional parameters I need. ie. deviceToken, deviceId, & deviceType
My request worked fine while the deviceToken parameter was smaller. Now the company providing me with my device token has made an excessively huge one. And now my request returns Bad Request 400.
AgTGERCBaS3d8n2QWxF9EtwcLktIoygoXpc8Y42ObZWja3RSjN%2bFBeshaY4ASainj3MusBbVopXbUFQrrgXUOSkAbOA7tChNKOFNKQ2gB8sEfCe5Du9BZufW4bAP5312MKRqV8g%3d
If I remove these characters from the end of my query string, the request goes through successfully. "Q2gB8sEfCe5Du9BZufW4bAP5312MKRqV8g%3d"
I have done some research and discovered that the max for a parameter is 255 characters. My device token is only 140.
To add to my confusion, if I change the order of the deviceId and deviceToken parameters, then I must shorten the deviceId parameter to send successfully. Another point of interest is that if I try to shorten any of the other parameters, then my request still fails. I must always shorten the second parameter.
Has any one else had similar problems and found a solution?
How can I send my looong device token via a query string at the end of a path?
It's possible it's the length of your query string itself, not the parameter.
Try adding
<httpRuntime maxQueryStringLength="2500"
maxUrlLength="2500" maxRequestLength="2500" />
to your config and see if the error persists
I found the solution after posting this question. Such is often the way.
The device token was getting saved to a field that was NVARCHAR(100). Previously this was enough. The device token can now be at least 140 characters. I changed the field to NVARCHAR(255). The problem is fixed. No more Bad Request 400.

Multiple parameters passed in WCF client don't work (even when WebMessageBodyStyle is Wrapped)

Hi fellow StackOverflowers,
I've got a WCF service wrtten C# that i can succesfully consume from things like jquery.
I want to be able to consume it by adding a web service reference in C# and making calls in the code. Everything was rosy, until I added multiple parameters. When I try to call any Service method, I get this error:
Operation 'GetStopNames' of contract 'IPublic' specifies multiple
request body parameters to be serialized without any wrapper elements.
At most one body parameter can be serialized without wrapper elements.
Either remove the extra body parameters or set the BodyStyle property
on the WebGetAttribute/WebInvokeAttribute to Wrapped.
I googled and searched StackOverflow for ages, but everybody seemed to have their problem fixed by setting
BodyStyle=WebMessageBodyStyle.Wrapped
in the WebGet / WebInvoke attributes.
An example of one of my service methods in the interface:
[OperationContract]
[WebGet( BodyStyle=WebMessageBodyStyle.WrappedRequest
, UriTemplate = "GetOperators?appKey={apk}"
, RequestFormat = WebMessageFormat.Json
, ResponseFormat = WebMessageFormat.Json)]
ResultList GetOperators(string apk);
Is there something wrong with this?
I'm simply calling
ServiceReference1.PublicClient c = new ServiceReference1.PublicClient();
c.GetOperators("XXX");
inside the client, and it's breaking on the second line.
Any ideas? If there is any more data you need to help answer me, just add a comment :)
EDIT:
here are the excerpts of relevant bits from my Web.config files
http://pastebin.com/CyQNG6wk
EDIT:
shortcut to serviceContract that I linked in comments
http://pastebin.com/bvGmGtfd
I ended up switching to using WebApi but I'm keeping this question open since I'm still not sure why it was failing.
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "GetOperators?appKey={apk}",
BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json,RequestFormat=WebMessageFormat.Json)]
ResultList GetOperators(string apk);
In the .svc file make sure Service="Developer_Portal.Public"
Its the problem in GetStopNames. I assume it is Http Get (WebGet). Make sure all the parameters it accepts are defined in uri template
GetStopNames(string p1, string p2, string p3)
uri = "GetStopNames/{p1}/{p2}?param1={p3}" or GetStopNames?param1={p1}&param2={p2}&param1={p3} or whatever combination
You cannot generate proxy for rest by adding service reference. Do you have soap based service with same interface also?

REST webservice "Bad request"

I'm writing a REST webservice having a method like this:
[WebGet(
UriTemplate = "/Test/{p1}/{p2}",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml)]
public string Test(string p1, string p2)
{
// Do something here
}
So if I call basurl/Test/prova/test my method Test is invoked with p1="prova" and p2="test" and everything works fine.
Problem comes when I try to use a param having (for example) % char: even translating it in URL code, when I try to call basurl/Test/prova/te%25st I get a
Errore HTTP 400 - Bad Request.
If I use
[WebGet(
UriTemplate = "/Test/{p1}?p2={p2}",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml)]
public string Test(string p1, string p2)
{
// Do something here
}
and call basurl/Test/prova?p2=te%25st it works.
Why? What can I do to let first syntax work?
UPDATE:
Look at my answer with a possible solution.
If someone finds a better one, please post it!!
Thanks
Googling around I've just found this link:
http://weblogs.asp.net/imranbaloch/archive/2010/04/23/understanding-400-bad-request-exception.aspx
where they say:
ASP.NET Restrictions:
After passing the restrictions enforced by the kernel mode http.sys then the request is handed off to IIS and then to ASP.NET
engine and then again request has to pass some restriction from
ASP.NET in order to complete it successfully.
ASP.NET only allows URL path lengths to 260 characters(only paths, for example http://a/b/c/d, here path is from a to d). This
means that if you have long paths containing 261 characters then you
will get the Bad Request exception. This is due to NTFS file-path
limit.
Another restriction is that which characters can be used in URL path portion.You can use any characters except some characters
because they are called invalid characters in path. Here are some of
these invalid character in the path portion of a URL, <,>,*,%,&,:,\,?.
For confirming this just right click on your Solution Explorer and Add
New Folder and name this File to any of the above character, you will
get the message. Files or folders cannot be empty strings nor they
contain only '.' or have any of the following characters.....
For checking the above situation i have created a Web Application and put Default.aspx inside A%A folder (created from
windows explorer), then navigate to,
http://localhost:1234/A%25A/Default.aspx, what i get response from
server is the Bad Request exception. The reason is that %25 is the %
character which is invalid URL path character in ASP.NET. However you
can use these characters in query string.
The reason for these restrictions are due to security, for example with the help of % you can double encode the URL path portion
and : is used to get some specific resource from server.
So I'm starting to think that my problem is impossible to solve.
I'm sure that this problem is not present in some REST webservice written in PHP and hosted with Apache, so I think it's just a IIS/ASP "security" restriction I can't find a workaround for...
UPDATE WITH FINAL SOLUTION:
I found a solution here: read the article to understand everything.
You should know that it could be risky, so think well before using it.
<system.web>
<httpRuntime requestPathInvalidCharacters="" />
<pages validateRequest="false" />
</system.web>

Categories