ServiceStack routing GET requests to POST methods - c#

I have been having an issue with Uri too long for a number of GET requests we currently have and our proposed solution is to issue post requests instead.
I'd prefer to keep my service methods using the GetXResponse Get(GetXRequest request) signature.
Is there any way to configure ServiceStack to resolve to Get methods when the request starts with 'Get'?

Customize Request Handling with X-Http-Method-Override
There's no special heuristic of Request DTO naming to Get actions, but when making the request you can use the X-Http-Method-Override in either of the HTTP Header, QueryString or FormData to specify a different verb to execute the request as.
Handle any Verb with Any() method
You can also use Any method to handle all verbs (i.e. inc GET/POST), e.g:
GetXResponse Any(GetXRequest request) { .. }
The Any method is used as a fallback, if you also have specific verbs with the same Request DTO it will use those instead, i.e:
GetXResponse Get(GetXRequest request) { .. }
GetXResponse Post(GetXRequest request) { .. }

Related

Can you use custom HTTP request methods with http.client?

Is there a way to use HTTP request methods that are not implemented by System.Net.Http.HttpMethod?
I try to update files with a REST interface. The way it is implemented, I GET a list of files and their hashes. Then I check if any of these files have changed on my side and if so, I POST each file to the API, otherwise I skip it.
When I'm done, the endpoint expects an UPDATE request to know that I'm done sending files. But there is no UPDATE method in HttpMethod.
Is there a way to alter REQUEST_METHOD manually in a HttpRequestMessage or do they need to recode the endpoint?
Looking up System.Net.Http.HttpMethod only gives the following options: GET, PUT, POST, DELETE, HEAD, OPTIONS, TRACE, PATCH and CONNECT. There is no obvious way to add a custom method.
In the case where you need an HttpMethod that does not exist in the static properties of the class, you can just use the constructor which allows you to pass any string method:
var customHttpMethod = new HttpMethod("UPDATE");

Url Referrer is not available in WebApi 2 MVC project

I have an MVC WebAPI 2 project with a Controllers controller. The Method I'm trying to call is POST (Create). I need to access the referring URL that called that method yet, no matter what object I access, the referring URL either doesn't exist in the object or is null.
For example, I've added the HTTPContext reference and the following returns null:
var thingythingthing = HttpContext.Current.Request.UrlReferrer;
The Request object does not have a UrlReferrer property.
This returns null as well:
HttpContext.Current.Request.ServerVariables["HTTP_REFERER"]
I cannot modify the headers because I need to be able to generate a link to the method and filter access by origin of the call.
Any particular place I should be look or, alternatively, any particular reason why those are returning null?
Edit: I have a solution for GET methods (HttpContext.Current.Request.RequestContext.HttpContext.Request.UrlReferrer) but not for POST methods.
See this answer. Basically, WebAPI requests use a different kind of request object. You can create an extension method that provides a UrlReferrer for you, though. From the linked answer:
First, you can extend HttpRequestMessage to provide a UrlReferrer() method:
public static string UrlReferrer(this HttpRequestMessage request)
{
return request.Headers.Referrer == null ? "unknown" : request.Headers.Referrer.AbsoluteUri;
}
Then your clients need to set the Referrer Header to their API Request:
// Microsoft.AspNet.WebApi.Client
client.DefaultRequestHeaders.Referrer = new Uri(url);
And now the Web API Request includes the referrer data which you can access like this from your Web API:
Request.UrlReferrer();

HttpClient DeleteAsync with Multiple records

I'm using the sendgrid api here:
https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/contactdb.html#Delete-a-Recipient-DELETE
and it shows passing an array of strings to the DELETE call. When I look at the signature of System.Net.Http.HttpClient, DELETE does not allow for content to be passed in.
Is there a standard around DELETE that does not allow for multiple content passed at the same time?
API definition:
The HTTP/1.1 RFC states that a DELETE request's payload has no defined semantics.
It's not illegal to include a payload, but this means that if a payload is included, it should be ignored.
Many HTTP clients, such as the one provided by the .NET framework, don't provide an interface to include a payload when it has no defined semantics for the method.
Unfortunately, many REST APIs do require a payload with these methods. You can accomplish this by manually creating a HttpRequestMessage object, setting the Method and Content properties, and passing it to the HTTP client's SendAsync method.
Create an extension method
public static class HttpClientExtensions
{
public static Task<HttpResponseMessage> Delete(this HttpClient client, HttpContent content)
{
var request = new HttpRequestMessage { Method = "DELETE", Content = content);
return client.SendAsync(request);
}
}
However I cannot recommend it, as it breaks basic assumptions of HTTP, which allows efficient HTTP Proxies to work.
The "correct method" around this problem is to use HTTP 2.0 (or HTTP 1.1 Pipelining, which is deprecated due to it being mostly broken, but you could try it out) to create multiple DELETE requests. In theory that solution does not require any code change.

How do I set out Attribute in Api Controller

is it possible to use out attribute in a Api Controller method? I'm using C#.
for exp:
[HttpGet]
public string GetWhatever(string type, string source,out int errorCode, out string errorMessage)
if it is, an example of how to call it and get the out value would be great.
No, this is not possible. Only the return value is used and sent to the client.
You should sent a proper HTTP status code and the error message in body. Have a look at this: http://www.asp.net/web-api/overview/error-handling/exception-handling
I believe you miss-understand the usage of the Web API.
Your Web Api method will not be called like any other C# class method, unless you access the library directly and reference the api controller and its method like any other C# class.
The method will be called via the ASP.NET action selector and that will depend on your HTTP verb (GET, PUT, POST, DELETE or PATCH) and depending on the type and the number of your parameters.
Now your method can return your data or returns error depending on your situation, but eventually all your responses will convert to statuscode/content/error,...etc which is what the HTTP protocol understands and deals with.
for example your method can return Ok Status code (200), or Notfound status code 404 depending on where your request found the requested resource or not.
You can start with this article about Web API 2, hopefully you get a better understanding.
Hope that helps.

Is it possible or necessary to set the content type of a ServiceStack client delete request?

I have the following code.
public T SendUpdateRequest(string url)
{
using (JsonServiceClient client = new JsonServiceClient())
{
T response = client.Put<T>(url);
return response;
}
}
I have similar methods for create and delete requests, calling the JsonServiceClient Post and Delete methods respectively.
When calling my update or create methods, the call to the external API works fine. Delete does not. I can see that the API's delete method does indeed work if I fire a request to it via REST console.
When I compare my non-working delete with the working one's request/response in Fiddler, I can see the main difference is my request is not setting content-type to application/json (all these methods return JSON).
My question is, is it possible (or even necessary) to explicitly set the content-type of my delete request to application/json in order to successfully call my API method?
The ServiceStack clients do not set the content-type header on requests where there is no request body, as the content-type only applies to the body, and is therefore redundant.
This can be seen here in the code that prepares the client request.
if (httpMethod.HasRequestBody())
{
client.ContentType = ContentType;
...
A correctly implemented RESTful service should be happy with a DELETE request without content-type being specified where there is no body.
DELETE /User/123 HTTP/1.1
If the service you are calling is not happy with your request without this type being specified (which is unusual), then you can manually enforce the sending of the type using this filter:
var client = new JsonServiceClient("https://service/");
client.RequestFilter += (httpReq) => {
// Force content type to be sent on all requests
httpReq.ContentType = "application/json";
};
I hope that helps.

Categories