Is it possible to use JSONP on the server? - c#

I'm stuck on a clients host that has medium trust setup which blocks cross domain requests and need data from a 3rd party domain. I now have the option to use JSONP.
I've used JSONP from the client with jQuery to get around the browsers cross domain security and I've used HttpWebRequest in ASP.Net 3.5.
Is it possible to use JSON on the server and if so how?
I don't think it is, but worth asking seeing as I already have this app written server side....
Thanks,
Denis

The easy way might be just to proxy the JSONP request through your server. If that isn't an option (because the data must be processed in some way on the server) you can manually strip off the function-call from the return and then JSON-parse the rest
So if the JSONP call returns:
F001( { "moose" : "sister" } )
First, erase everything up to the first parenthesis and after the last so you have
{ "moose" : "sister" }
And parse that into whatever you need.

Related

Proprietary bare-bone ASP web service

I want to create a proprietary minimal / bare-bone / data-light webservice. I prefer not to use the standard solutions like Restful, WebAPI, SOAP, WCF, etc.
I just want a web server listener that can receive and process 1 UTF8 string (own message format) and respond with 1 UTF8 string as the result.
My question is: can you give me a starting point, by providing a code example of the interface. Of course not the complete implementation.
Data transfer has to be as minimal as possible (no avoidable headers).
NB: Server language has to be .NET. Code example may be in C# or VB.
The most bare-bone thing to create a web service would be an HTTP Handler.
The sample I linked returns HTML but you could send back XML as well (or anything else really, just make sure to return an appropriate Content Type).
The call to your method would be a regular HTTP call of the URL of your Handler.

Validate SharePoint REQUESTDIGEST for a GET request?

I have a WCF REST service hosted in SharePoint that uses SSOM. The client web application sends AJAX requests containing the REQUESTDIGEST in a X-RequestDigest header. I am using the typical SPWeb.ValidateFormDigest() for my POST requests to prevent CSRF vulnerabilities. Works great.
Here's the weird part. Our client uses HP Fortify, and it is reporting that our GET requests are vulnerable to CSRF attacks. My GET requests are indempotent so this seems silly, but I must be compliant.
To get around it, I want to use ValidateFormDigest() in my WCF method for the GET request the same way I do for POST, but it throws this exception:
"Updates are currently disallowed on GET requests. To allow updates on a GET, set the 'AllowUnsafeUpdates' property on SPWeb."
I tried setting AllowUnsafeUpdates, but that just makes the request succeed without validating the digest!
Is there a way to have SPWeb validate the digest within a GET request?
HP Fortify gives recommendations, not edicts. If you think - and can prove - that the warning is spurious, then justifying the pattern should be treated as being compliant. Code analysis tools are not perfect.

Testing a REST Logging Web Service using C#

I've created a pretty basic REST Web Service in VS2012 using C#. The approach I've taken is seen below in one example:
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "OpenSession/{key}/{source_userid}/{source_id}/{source_version}/{source_ip}")]
string OpenSession(string key, string source_userid, string source_id, string source_version, string source_ip);
The code works just fine and the service is up and running. I get responses, the tokens are handed out, etc. I figured wrapping the data in the URL was just fine as the service is built for logging, so in the end, calls would be (for example):
www.service.site/service.svc/2/5/12/HELLO
(BTW if there's a better way to do this while keeping it a REST service please let me know)
The problem I have is... how do I test this properly? I need to simulate 1,000 concurrent hits to this service and have built a custom C# Windows Application to do this, but I'm encountering a number of problems.
First, I have no idea how to use HttpWebRequest and the stream readers/writers to send/receive data properly in a manageable format. I see The requests have GET and PUT methods, etc. but I honestly can't seem to make heads or tails of separating the post data vs. the URL information. AFAIK I'm not really posting any data as all my data is embedded in the URL request itself; is this correct?
Also, I have no idea what "content type" to set the HttpWebRequest to in order to be compatible with my Operation Contract (I can see the enumeration of JSON but what's the "text" supposed to be?)
And on top of that, HttpWebRequest is monstrously slow. When I open a URL directly to the service (e.g. "http://localhost:51849/Scribe.svc"), it's fast, but the second I try to call a method (e.g. ""http://localhost:51849/Scribe.svc/GetStatus"), I get a 1.5-2 second delay (and I've done all the proxy fixes to ensure it's as fast as possible).
Any help would be greatly appreciated.
I don't know if you are aware of this utility:
SoapUI
You can use it to reference your service and generate the requests to test your service.
The installation is pretty straightforward. After installed, you have to click on file/new SoapUI Project.
Then, in the popup window, you fill in the "Initial WSDL/WADL:" field with your service's wsdl, like this:
http://localhost:51849/Scribe.svc?wsdl
It'll generate the client to correctly do the calls to your service.
Using soap ui you can even test doing a bunch of calls to stress up your service.
This is a good way to test your services.
AFAIK I'm not really posting any data as all my data is embedded in the URL request itself; is this correct?
Yes. That's how a GET request works. The data is passed on your url. You should only use GET requests when not changing the state of the data on the server, otherwise you should use post.
PUT methods you'll use when you want to create/update the data on the server.
I hope it helps.
Regards,
Rodrigo
Maybe you should consider using some performance tool.
There are plenty and them, should be easy to find one suitable for your pourpose.
Jmeter could be a good option.
This is a guide that show how to use Jmeter to test a REST Web Service.
Hope it can help.
Thanks for the responses! I actually have the testing system working now and can slam my service with thousands of timer-controlled sessions. The key to getting around the PUT request issue was to use empty settings:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "PUT";
req.ContentType = "application/json";
req.ContentLength = 0;
I did look at those tools, but for my specific needs, I found writing a custom timer-controlled app was the best approach.
I'm not sure if the delay is still problematic, or possibly even linked to the debug state. once I publish the service to Azure and test it remotely, I'll get a better idea if there's any latency issues with connectivity which are service based...

Consuming a web service using POST instead of the going the usual WSDL route

This is how I have currently managed to consume a particular Microsoft web service. Notice that it is located on an HTTPS server and that it requires a username, a password, and a .cer file to be installed in the operating system's "root certificate authorities".
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.NegotiateServiceCredential = true;
binding.Security.Message.AlgorithmSuite
= System.ServiceModel.Security.SecurityAlgorithmSuite.Default;
binding.Security.Message.EstablishSecurityContext = true;
EndpointAddress endpoint = new EndpointAddress("https://address.of.service");
//"GreatClient" was created for me automatically by running
//"svcutil.exe https://address.of.service?wsdl"
GreatClient client = new GreatClient(binding, endpoint);
//Username and password for the authentication. Notice that I have also installed
//the required .cer certificate into the system's "root certificate authorities".
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
//Now I can start using the client as I wish.
My question is this: How can I obtain all the information necessary so that I can consume the web service with a direct POST to https://address.of.service, and how do I actually perform the POST with C#? I only want to use POST, where I can supply raw XML data using POST directly to https://address.of.service and get back the result as raw XML data. The question is, what is that raw XML data and how exactly should I send it using POST?
(The purpose of this question: The reason I ask is that I wish to consume this service using something other than C# and .NET (such as Ruby, or Cocoa on Mac OS X). I have no way of knowing how on earth to do that, since I don't have any easy-to-use "svcutil.exe" on other platforms to generate the required code for me. This is why I figured that just being able to consume the service using regular POST would allow me to more easily to consume the service on other platforms.)
What you are attempting to do sounds painful to do now and painful to maintain going forwards if anything changes in the server. It's really re-inventing the wheel.
If you haven't considered it already, I would:
(a) Research whether you can use the metadata you have for the service and use a proxy generator native to your target plaform. There aren't many platforms that don't have at least some tooling that might get you part of the way if not all of it. Perhaps repost a question targetting Ruby folk asking what frameworks exist to consume an HTTPS service given it's WSDL?
(b) Failing that, if your scenario allows it I would consider using a proxy written in C# that acts as a facade for the service which translates it into something easier to consume (for example, you might use something like ASP.NET MVC WebAPI which is flexible and can easily serve up standards compliant responses over which you can maintain total control).
I suspect one of these may prove easier and more valuable than the road you are on at the moment.
I had to go through something similar when porting .NET WCF code to other platforms. The easiest approach I found was to enable message logging on the WCF client. This can be configured to save both envelope and body and once everything is working on the .NET side of the house, you can use the message log to have "known-good" XML request/response to port to other platforms.
I found this approach to be more elegant since I didn't have to add an additional behavior to log messages, and it can be easily enabled/disabled/tweaked in the config. The Service Trace Viewer Tool that ships with Visual Studio is also handy for reviewing the log files.
I think when you say that the service should be consumed from other platforms, which do not have proxy class generation logic, you can go with REST services. This will allow you to create input as simple string concatenation instead of complex XML. Though its applicability depends on the situation.
Check this discussion : http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/6907d765-7d4c-48e8-9e29-3ac5b4b9c405/
As far as the certificate is concerned, refer http://msdn.microsoft.com/en-us/library/ms733791.aspx on how to configure it.
I know this is not a very precise answer, but you will be the best person to evaluate above procedure, hence posted. Hope it helps.
What I'll do:
1- Create a small c# app that can post on this webservice (using svcutil). And modify it to show the XML send/received. To view the xml there are several ways: logging, wireshark etc. To add it directly to the small app there is another question here that give a good answer.
2- Once you know what you have to send, you can do it in c# like this:
// implement GetXmlString() to return the XML to post
string xml = GetXmlString();
// create the url
string url = new UriBuilder("http","address.of.service",80).ToString();
// create a client object
using(System.Net.WebClient client = new System.Net.WebClient()) {
// performs an HTTP POST
client.UploadString(url, xml);
}
I'm not a .NET programmer but I've had to interoperate with a few .NET services and have lots of SOAP/WSDL experience. Sounds like you've captured the XML for your service. The other problem you'll face is authentication. OOTB, .NET web services use NTLM for authentication. Open-source language support for NTLMv2 can be hit and miss (although a quick google search pulled up a few possibilities for ruby), and using NTLM auth over HTTP may be something that you have to wire together yourself. To answer a question above: where are the auth creds? If the service is using NTLM over the wire, authentication is happening at some layer below HTTP. If the service is using NTLM to authenticate HTTP, your NTLM creds are in the HTTP Authorization header. You should be able to tell with wireshark where they are. You'll also probably need a SOAPAction header; this can also be sniffed with wireshark. For the C# client, I'm sure there are docs explaining how to add headers to your request.

Append an HTTP header to all IE requests

I have a scenario which requires me to append an HTTP header to all outgoing IE-based HTTP communications on a machine. This doesn't need to work outside of IE.
I first attempted to create a simple HTTP proxy in C#, but the performance of this proxy wasn't very good, and there were issues with HTTPS communications.
My second attempt was to use FiddlerCore, which I hoped would have better performance, but was only marginally faster than what I had created myself.
Aside from writing a TCP filter driver to do this (not in my skillset), is there another option? Strictly speaking, this doesn't have to be an HTTP header. It could even be something I tack on to the user agent string.
I was thinking perhaps about creating a simple BHO, but I'm hoping there is an easier solution... one that I can write in C# perhaps.
How about just reading the user-agent string in your code and if it's IE then append the HTTP header?
Just use user agent string. It is documented here http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx .
Per article following registry key can be used to add to the user agent string: SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\User Agent\Pre Platform\Token = Value.

Categories

Resources