I am implementing the Logging of the request and response in ServiceStack. I wanted to get hold of IHttpRequest in my IRequestLogger.Log() method.
The IRequestContext does not have info like the IHttpRequest, Is there a way I can get that passed or accessed. I am trying to log the Request Headers, UserAgent, token etc.
The IRequestLogger.Log is injected with the current IRequest.
You can cast to IHttpRequest for HTTP Requests as well as get access to the underlying ASP.NET or HttpListener request by casting IRequest.OriginalRequest, e.g:
void Log(IRequest request, object requestDto, object response, TimeSpan elapsed)
{
var httpReq = request as IHttpRequest;
var aspReq = request.OriginalRequest as HttpRequestBase;
}
Related
I'm writing a backend using ServiceStack. our main front end client is an Angular 2 application using TypeScript. To that end, we are using the DTOs that are generated by the services when hitting /types/typescript and /types/typescript.d. This all works fine and good using the JsonServiceClient... but it seems that the response status code is somehow wrapped up in the call and not returned as it as when using a standard XHR call.
Finding the AddResponseStatus configuration item, I changed the service configuration to add this on any DTO that didn't already have the property (which mine didn't):
var ntf = new NativeTypesFeature();
ntf.MetadataTypesConfig.AddResponseStatus = true;
Plugins.Add(ntf);
After refreshing the TypeScript reference, I can see that all DTO types returned now have a ResponseStatus property on them.
export class QueryReportResponse
{
Data: string;
ResponseStatus: string;
}
Here is a scrubbed return (removed the 'Data' portion) showing the property exists on the object:
<QueryReportResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/blah.blah.ServiceModel.Messages">
<Data>
blah blah data here
</Data>
<ResponseStatus i:nil="true"/>
</QueryReportResponse>
Now, I assumed (wrongly so) that by doing this, some sort of status would be set 'automatically'. I'm obviously not right here, as this property is not set. My front end guy is asking to be able to see the status on all returned calls, like he was able to before when using straight XHR prior to using the JsonServiceClient, as now he cannot see the return status.
What is the intent of this field? I cannot set it manually, as it's added by ServiceStack dynamically at runtime. I can only assume that I would have to create my own base class return DTO of sorts and set that on the way back to the caller... can someone help me understand the purpose of this field? Thanks.
ServiceStack's Add TypeScript Reference is typically used with the TypeScript servicestack-client. The ResponseStatus is used in ServiceStack's Error Handling which is used to capture structured Error Information. It's not populated for successful responses and it's distinct from the HTTP Response Status code although if throwing a HTTP Error the ResponseStatus.ErrorCode will typically contain the HttpStatusCode enum string.
Adding ResponseStatus on DTOs
Adding the ResponseStatus on DTOs, e.g:
ntf.MetadataTypesConfig.AddResponseStatus = true;
Just adds the ResponseStatus on generated DTOs where they didn't previously exist. It doesn't have any effect on Response DTOs which already includes the ResponseStatus property, e.g:
public class MyResponse
{
public ResponseStatus ResponseStatus { get; set; }
}
Accessing HTTP Status Responses
Developers shouldn't care what the HTTP Status code is for successful responses (which is almost always 200 OK). ServiceStack's TypeScript JsonServiceClient will just return the Typed Response DTO for successful responses, e.g:
var response = await client.post(request)
They should only be interested for handling error responses, however it's expected to use the ResponseStatus.ErrorCode to determine the type of Error and apply application error handling logic, e.g:
try {
var response = await client.post(request)
} catch (e) {
console.log(e.responseStatus.errorCode);
}
If they really want the HTTP Status they can get it using a response filter, e.g:
var status = null;
try {
client.responseFilter = res => status = res.status;
var response = await client.post(request)
} catch (e) {
console.log(status, e.responseStatus.errorCode);
}
I am trying to make a RESTful web service using NServiceKit version 1.0.43. I want this to work without an outside service that is not including a ContentType in their header request. My web service is rejecting the calls with a "406 Unaccepted Content Type" although I have not set a default content type. How do I allow calls to this service without defining a ContentType?
I did something similar with a RequestFilterAttribute in ServiceStack 4.x. It may need some tweaking to work on NServiceKit's fork, but this gives you the general idea. If a Content-type header is not sent in, it defaults it to JSON:
public class ContentTypeFixFilter : RequestFilterAttribute
{
public override void Execute(IRequest req, IResponse res, object requestDto)
{
if (!req.Headers.AllKeys.Contains("content-type", StringComparer.CurrentCultureIgnoreCase))
{
req.ResponseContentType = MimeTypes.Json;
}
}
}
}
My Servicestack service is beeing posted Json (by jquery).
sendData = function(dataToSend) {
var request;
return request = $.ajax({
url: "/api/test",
type: "post",
data: JSON.stringify(dataToSend),
dataType: "json",
accept: "application/json",
contentType: "application/json"
});
The Json data is correctly deserialized if it corresponds to the root properties of my DTO (eg: userId:'foo' -> UserId=foo in the DTO).
I want to access the raw json posted data before it gets deserialized for adding custom deserialization.
Till now I had no problems accessing the querystrings with custom filters (RequestFilterAttribute) or if data vas posted like form.
Now I see the data that gets posted with Chrome Developer Tools is in the headers with "Request Payload" so it is nor in FormData and nor QueryString I can access when debugging my IHttpRequest.
How can I get my raw json data in the filter?
If you want to replace the default deserialization behavior with custom behavior for a specific request DTO, you can do this in your AppHost setup code:
JsConfig<MyRequestDtoClass>.DeSerializeFn = DeserializeMyRequestDto;
Where DeserializeMyRequestDto is a function or lambda taking a single string param - the raw request body - and returning the deserialized instance of your DTO:
MyRequestDtoClass DeserializeMyRequestDto(string rawBody) { ... }
RequestFilterAttribute subclasses purpotedly have access to the raw request body using request.GetRawBody(), where request is the IHttpRequest object passed into the filter's Execute method. But in my experience, GetRawBody returns an empty string, because the request input stream seems to be consumed by that time due to the deserialization. I worked around this once by creating an HTTP module (registered in AppHost via DynamicModuleUtility.RegisterModule) that would "peek" at the request input stream in a BeginRequest event handler. (The "peek" function would read the request input stream and then reset the Position of the stream to where it initially was.)
I'm trying to send custom HTTP Headers with a JsonServiceClient but headers are never sent in the query.
I'm using:
JsonServiceClient client = new JsonServiceClient (baseUri);
client.Headers.Add ("X-Parse-Application-Id", "XXXXXX");
client.Headers.Add ("X-Parse-REST-API-Key", "XXXXXX");
Any idea ?
You haven't made a request yet. The Headers get added here when you make a request.
An alternative way to add headers is to use the Request filters, e.g:
client.RequestFilter = httpReq => {
httpReq.Headers.Add ("X-Parse-Application-Id", "XXXXXX");
httpReq.Headers.Add ("X-Parse-REST-API-Key", "XXXXXX");
};
Which effectively does the same thing.
Here is another way to do it.
_client.RequestFilter = httpReq => httpReq.Headers.Add("X-CUSTOM", "hello");
have created REST service using servicestack and in post request I have return object in following way
return new HttpResult(request)
{
StatusCode = HttpStatusCode.Created,
};
request: object which i have posted in database
When i check it in fiddler it render whole HTML Page of servicestack in response body, instead of that i would like to return Status code only, so please tell me how can i do?
Thanks
There was a bug in versions before < v3.05 that did not respect the HttpResult ContentType in some scenarios, it should be fixed now with the latest version of ServiceStack on NuGet or available from:
https://github.com/ServiceStack/ServiceStack/downloads
Prior to this you can still force the desired ContentType by changing the Accept:application/json Request Header on HttpClient or by appending ?format=json on the querystring of your url.
So now if you don't want to have any DTO serialized, you don't add it to the HttpResult:
return new HttpResult() { StatusCode = HttpStatusCode.Created };
Note you still might get an empty Html response back if calling this service in the browser (or any Rest Client that Accepts:text/html). You can force a ContentType that won't output any response if it has empty payload (e.g JSON/JSV) by specifying it in the result as well, e.g;
return new HttpResult() {
StatusCode = HttpStatusCode.Created,
ContentType = ContentType.Json
};