Reputation: 73
Trying a setup with ServiceStack 3.9.49 and CORS.
A simple Echo
Service which returns the POST
ed data back++. The code:
[Route("/echo")]
public class EchoRequest
{
public string Name { get; set; }
public int? Age { get; set; }
}
public class RequestResponse
{
public string Name { get; set; }
public int? Age { get; set; }
public string RemoteIp { get; set; }
public string HttpMethod { get; set; }
}
public class EchoService : Service
{
public RequestResponse Any(EchoRequest request)
{
var response = new RequestResponse
{
Age = request.Age,
Name = request.Name,
HttpMethod = base.Request.HttpMethod,
RemoteIp = base.Request.RemoteIp
};
return response;
}
}
The AppHost Configure
code:
public override void Configure(Container container)
{
ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;
SetConfig(new EndpointHostConfig
{
DefaultContentType = ContentType.Json,
GlobalResponseHeaders = new Dictionary<string, string>(),
DebugMode = true
});
Plugins.Add(new CorsFeature());
PreRequestFilters.Add((httpRequest, httpResponse) => {
//Handles Request and closes Responses after emitting global HTTP Headers
if (httpRequest.HttpMethod == "OPTIONS")
httpResponse.EndServiceStackRequest();
});
RequestFilters.Add((httpRequest, httpResponse, dto) =>
{
httpResponse.AddHeader("Cache-Control", "no-cache");
});
}
When sending a POST
(with the json object in the body) with Content-Type: application/json, everything works great.
But when sending the same content and setting the Content-Type
to text/plain
, the correct method gets invoked, but the data in the EchoRequest
is null
.
Is this the correct behaviour? Must the Content-Type
be set to application/json
if a json object is sent as a POST
?
Is yes, is it possible override this somehow e.g. in the url? From my understanding using ?format=json in the url, only affects the returned data...
Final question, is it possible to modify the Content-Type
header of the request before being deserialized to the method, somewhere, something like this:
if (httpRequest.ContentType == "text/plain")
httpRequest.Headers["Content-Type"] = ContentType.Json;
Upvotes: 2
Views: 507
Reputation: 3324
Deserializing into an empty object is the correct behavior for ServiceStack's serializer. It tends to be very forgiving. It creates an empty deserialized object and proceeds to hydrate it with anything it parses out of the input, meaning if you give it junk data, you will get back an empty object.
You can make the serializer less forgiving by specifying the following option in your AppHost config:
ServiceStack.Text.JsConfig.ThrowOnDeserializationError = true;
I am not aware of any way to modify the URL to indicate to ServiceStack that the request is in JSON format. Furthermore, it doesn't appear there is any way inside ServiceStack to modify the content type before deserialization. Even specifying a PreRequestFilter to modify the header before will not work as the request's ContentType property has been set and is readonly.
PreRequestFilters.Add((req, res) => req.Headers["Content-Type"] = "application/json");
Upvotes: 3