ProtocolViolationException Load testing web service (GET action with content-body) - visual-studio-2010

I created an ASP.NET MVC4 Web API service (REST) with a single GET action. The action currently needs 11 input values, so rather than passing all of those values in the URL, I opted to encapsulate those values into a single class type and have it passed as Content-Body. When I test in Fiddler, I specify the verb as GET, and enter the JSON text in the "Request Body" input box. This works great!
The problem is when I attempt to perform Load Testing in Visual Studio 2010 Ultimate. I am able to specify the GET action and the JSON Content-Body just fine. But when I run the Load test, VS reports exceptions of type ProtocolViolationException (Cannot send a content-body with this verb-type) in the test results. The test executes in 1ms so I suspect the exceptions are causing the test to immediately abort. What can I do to avoid those exceptions? I'd prefer to not change my API to use URL arguments just to work-around the test tooling. If I should change the API for other reasons, let me know. Thanks!

I found it easier to put this answer rather than carry on the discussions.
Sending content with GET is not defined in RFC 2616 yet it has not been prohibited. So as far as the spec is concerned we are in a territory that we have to make our judgement.
GET is canonically used to get a resource. So you are retrieving this resource using this verb with the parameters you are sending. Since GET is both safe and idempotent, it is ideal for caching. Caching usually takes place based on the resource URI - and sometimes based on various headers. The point is cache implementations - AFAIK - would not use the GET content (and to be honest I have not seen any GET with content in real world). And it would not make sense to include the content in the key generation since it reduces the scalability of the caches.
If you have parameters to send, they must be in the URI since this is part of what defines that URI. As such, I strongly believe sending content with GET is wrong.
Even when you look at implementations such as OData, they put the criteria in the URI. I cannot imagine your (or any) applications requirements is beyond OData query requirements.

Related

Getting the request body of search response with 2.X NEST client

I'm using the new 2.X NEST client. That part is important, because there were a great many breaking changes which will effect potential answers here.
Previously, I used the Glimpse Elasticsearch plugin to see the underlying queries being generated by NEST. However, it would appear that that plugin is no longer compatible with 2.X NEST. As a result, I'm trying to find a workaround to see the JSON query. The problem here is that the old way of accessing response.RequestInformation to get at the request body is gone. It seems to have been replaced with a combination of ApiCall, CallDetails, and DebugInformation. The problem here is that in all of these the request byte array is null unless you add .DisableDirectStreaming() to the ConnectionSettings instance you pass into ElasticClient. The problem there is that I'm handling all that using dependency injection with Ninject, so in something like a controller action, I have no access to the ConnectionSettings instance to make such a change. I suppose I could just add .DisableDirectStreaming() globally, but I have no idea what the potential consequences of that is and the documentation on this is frustratingly sparse.
So, there's a few avenues for an answer here, any of which I'll accept. First, if anyone has manage to get the Glimpse plugin functioning with 2.X, I'd love to know what you did. However, based on the fact that the underlying API has changed dramatically, my assumption is that the plugin is fundamentally broken until someone branches it for 2.X or Elastic comes out with their own version (which is supposedly coming at some undetermined point in the future).
Second, if there's some way to get at the request body without disabling direct streaming, and I simply missed it. I'd appreciate guidance there.
Third, if anyone has any ideas for how I can disable direct streaming at the controller action level, without affecting my Ninject setup or applying it globally, feel free to chime in.
Finally, it would be great if someone from the Elastic team can enlighten me to the effects of disabling direct streaming and what potential problems can arise from that, so I can make a determination about whether it would be wise to apply it globally or not.
With .DisableDirectStreaming() set to true, the request bytes and response bytes are buffered in memory streams to enable them to be available on the response via response.RequestBodyInBytes and response.ResponseBodyInBytes, respectively.
By default, it is set to false so the request type e.g. SearchDescriptor<T>, SearchRequest<T>, etc. is serialized directly to the request stream of the http request and similarly, the response type is deserialized from the response stream. The overhead of setting it to true is therefore keeping the request and response bytes around in memory for the lifetime of the response (and GC kicking in).
With Connection Settings, it's best to have one instance for the lifetime of the application; Serialization settings are cached per connection settings as well as caches for field and property expressions. There's no way currently to keep the request and response bytes around on a per request basis i.e. ad-hoc introspection, but I think this would be a useful addition; I'll add an issue for it :)
I'm not personally overly familiar with the Glimpse integration but I would expect it would require updating to work with NEST 2.x because of some of the changes. Having just given it a brief look, the changes look pretty straightforward. Looks like this can be done without having to set .DisableDirectStreaming() to true, but only grabbing the request bytes before they're written to the request stream.

4GL and Magento SOAP API. Need a simple example

My company runs a 4GL application internally. It's very old and no one really knows how to improve/develop for it since the developers are long gone.
I need to make a simple SOAP call to my Magento web store. There are tons of examples online in a multitude of languages, but I can't find a single 4GL (OpenEdege ABL) example.
I'm trying to set SKU's to Out of stock status.
Does anyone have a simple example that I can look at, or at least a starting point since there seems to be so little information on 4GL on the web.
Example of the call I need in PHP:
<?php
$proxy = new SoapClient('http://www.domain.com/api/soap/?wsdl');
$sessionId = $proxy->login('admin', 'password');
$proxy->call($sessionId, 'product_stock.update', array('sku123', array('qty'=>50, 'is_in_stock'=>1)));
For version 10.2B there's built in support for consuming web services in Progress ABL.
This is a basic tutorial of how to create a client for a SOAP-based web service in ABL. It's not best practices or in any way complete. Just a quick guide to get started.
1. Analyse the WSDL
There's a built in tool available via command line that lets you analyse a WSDL and create documentation about available services, datatypes, syntax etc. Invoke it on your wsdl like this:
proenv> bprowsdldoc yourwsdl-file c:\temp\docs
The wsdl can be local or remote. If its remote you specify the URL, if it's local you can specify just the local complete path. Documentation in html format will end up in c:\temp\docs. Open up index.html in that folder.
2. Create a basic client
In the index.html document there's a number of headings. Click the link under "Port types". In the Port Type document you will find some useful data.
Copy-and-paste the example in "Connection Details" into your Progress Editor. It should look something like this (names of services and procedures will be different - they are defined in the wsdl):
DEFINE VARIABLE hWebService AS HANDLE NO-UNDO.
DEFINE VARIABLE hYYY AS HANDLE NO-UNDO.
CREATE SERVER hWebService.
hWebService:CONNECT("-WSDL 'file_or_url_to_wsdl.wsdl'").
RUN XXX SET hYYY ON hWebService.
If you run this code your client is connected to the web service but it's still not doing anything.
Further down the same document there's a heading called "Operation (internal procedure) details". This is where the actual web service is invoked. It will look something like the code below. It actually show two ways of making the same call, one functional call and one procedural so choose whatever you prefer and insert it into your editor (I'm usually using the procedural for no real reason other than old habits):
DEFINE VARIABLE strXMLRequest AS CHARACTER NO-UNDO.
DEFINE VARIABLE ProcessXMLResult AS CHARACTER NO-UNDO.
FUNCTION ProcessXML RETURNS CHARACTER
(INPUT strXMLRequest AS CHARACTER)
IN hYYY.
/* Function invocation of ProcessXML operation. */
ProcessXMLResult = ProcessXML(strXMLRequest).
/* Procedure invocation of ProcessXML operation. */
RUN ProcessXML IN hYYY (INPUT strXMLRequest, OUTPUT ProcessXMLResult).
Now all you need to end your program is disconnecting and cleaning up. So insert:
hWebService:DISCONNECT().
DELETE OBJECT hWebService.
If you've followed all steps you should have a skeleton for invoking a web service. The only problem is that you need to handle the in- and out-data.
3. Handle the answer and the request
Depending on how the web service is built this can be easy (if you only input and output simple data like strings and numbers) or quite complicated (if you input and output entire xml-documents). The documentation you created in step one lists all datatypes (in the index.html document) but it doesn't offer any support in how you create any needed xml documents. There's specific Progress documentation available on how to work with xml...
The better approach is to take a look at the official documentation. There you will find everything above and more - how to handle errors etc.
Here is an overview of all 10.2B documentation and here is the PDF named Web Services.
Here is a link to a complete (but actually not so good) example in the Progress KnowledgeBase where a client and corresponding request/response xml is created and handled.
Look at these chapters:
6 - Creating an ABL Client from WSDL
7 - Connecting to Web Services from ABL
8 - Invoking Web Service Operations from ABL
That will basically take you through the entire process from start to beginning.

Why is ServiceStack caching in Service, not FilterAttribute?

In MVC and most other service frameworks I tried, caching is done via attribute/filter, either on the controller/action or request, and can be controlled through caching profile in config file. It seems offer more flexibility and also leave the core service code cleaner.
But ServiceStack has it inside the service. Are there any reason why it's done this way?
Can I add a CacheFilterAttribute, but delegate to service instead?
ToOptimizedResultUsingCache(base.Cache,cacheKey,()=> {
// Delegate to Request/Service being decorated?
});
I searched around but couldn't find an answer. Granted, it probably won't make much difference because the ServiceStack caching via delegate method is quite clean. And you seldom change caching strategy on the fly in real world. So this is mostly out of curiosity. Thanks.
Because the caching pattern involves, checking first to see if it is cached, if not to then execute the service, populate the cache, then return the result.
A Request Filter doesn't allow you to execute the service and a Response Filter means that the Service will always execute (i.e. mitigating the usefulness of the Cache), so the alternative would require a Request + Response filter combination where the logic would be split into 2 disjointed parts. Having it inside the Service, lets you see and reason about how it works and what exactly is going on, it also allows full access to calculate the uniqueHashKey used and exactly what and when (or even if) to Cache, which is harder to control with a generic black-box caching solution.
Although we are open to 'baking-in' built-in generic caching solutions (either via an attribute or ServiceRunner / base class). Add a feature request if you'd like to see this, specifying the preferred functionality/use-case (e.g. cache based on Time / Validity / Cache against user-defined Aggregate root / etc).

Xss Support - ASP.Net web api

Is there any built-in support for validating malicious input within the Web API, similar to forms with MVC?
If not, could anyone suggest a "global" filter/message inpector/whatever to validate against malicious input? I'm trying to avoid validating all of my models/parameters individually...
No, I don't believe there is such support. Here's why. The input validation support with Web Forms/MVC was a stopgap measure. But encoding output is the better XSS fix; validating input doesn't work perfectly, as what input is "bad" depends on how you'll be outputting it (as part of HTML element source, as part of JS source, in an HTML attribute value, as part of a SQL query, etc.).
So I'd recommend against generic, global input validation as the solution to XSS concerns. Instead, make sure you're always encoding input correctly before outputting it (or passing it on to another layer, such as a SQL DB). For output, if you're using the normal Web API mechanisms for returning data (model classes with content negotiation/formatters), the formatters should handle the content type-specific encoding for you.
I believe XSS is not relevant to ASP.NET Web API. Here is why I think so. Suppose, in the request body, say I get a JSON like this "input": "<script>alert('hello');</script>" and the web API stores the "input" which is bound to some property as-is into a database and retrieve it as-is in a subsequent GET request and sends that off to a client, it is still okay. It is the responsibility of the client to ensure this data is escaped correctly. So, when this input property is serialized to say a web application, before it writes to the browser, the client web app must HTML encode. Web API doing this generally does not make sense because a web API can be consumed by other clients say a WPF application where XSS may not be applicable. Or am I missing any specific case you have in mind?
Why dont you use HttpUtility.HtmlEncode?
Input should always be validated. It doesn't matter where it is going. A name field should return a name string, not a jpeg file or for example depending on your environment a SQL attack.

ASP.NET MVC 3: Purpose of IgnoreRoute("{resource}.axd/{*pathInfo}"); ? deprecated?

Do I even need this rule anymore?
I don't see any requests incoming for resource.axd files (as opposed to when I ran webform applications)
WebResource.axd is an HTTP Handler that is part of the .NET Framework
that does one thing and one thing only – it is tasked with getting an
embedded resource out of a DLL and returning its content. What DLL to
go to and what embedded resource to take are specified through the
querystring. For instance, a request to
www.yoursite.com/WebResource.axd?d=EqSMS…&t=63421… might return a
particular snippet of JavaScript embedded in a particular assembly.
Its still part of the framework and you can still retrieve embedded resources using the above handler. You dont want your route handler to handle such requests and that is why it is ignored. My guess is that you can get rid of it if you are completely sure that your app/libraries that you use dont use it.

Resources