ASP.NET WebAPI: How to control string content returned to client?
Asked Answered
V

2

17

In WebAPI, say I return a string wrapped in an HTTP response:

return Request.CreateResponse(HttpStatusCode.BadRequest, "Line1 \r\n Line2");

When invoking this action from jQuery, the response text is treated before it is returned. So in the xhr, I get something like this:

function success(xhr) {
    alert(xhr.responseText); // alerts ""Line1 \\r\\n Line2""
}

In other words, the string gets wrapped in double quotes, and special characters get escaped so that they appear in the output (actual alert is "Line1 \r\n Line2", so the newlines are not preserved, but rather encoded and shown in the response text).

I can get around this by removing the quotes and replacing the newlines on the client like so:

var responseText = xhr.responseText.substr(1, xhr.responseText - 2)
    .replace('\\r', '\r').replace('\\n', '\n');

But is there a way to tell WebAPI how to format string responses? For example, not to wrap them in double quotes and convert escaped characters?

Vagabondage answered 29/10, 2012 at 19:5 Comment(0)
D
18

This happens because your controller is returning JSON in which string values are quoted.

A simple solution is to parse the responseText as JSON and then you can use the value as intended:

$.ajax("/api/values/10", {
    error: function (xhr) {
        var error = JSON.parse(xhr.responseText);
        $("textarea").val(error);
    }
});

This correctly interprets the line breaks/carriage returns.

Alternatively you can specify the text/plain media type in your controller:

return Request.CreateResponse(
    HttpStatusCode.BadRequest, 
    "Line1 \r\n Line2", "text/plain");

Web API will then try and load an appropriate media type formatter for text/plain which unfortunately does not exist OOTB. You'll find one in WebApiContrib.

Duncan answered 29/10, 2012 at 20:40 Comment(4)
Thank you this is exactly what I was looking for. One final question, which is better: To add the media type formatter to the config and use "text/plain" as the 3rd argument to CreateResponse, or to use new PlaintTextFormatter() as the 3rd argument?Vagabondage
I would favour the first option since Web API will then locate the appropriate formatter from the configuration. If you ever change the formatter you only need to do it in one place.Duncan
Because the OP is returning a Bad Request (400) response. return Request.CreateResponse(HttpStatusCode.BadRequest, "Line1 \r\n Line2");Duncan
I'm using the suggested formatter above. It compiles but when running I'm getting an error on the ReadFromStreamAsync method "The type or namespace name 'HttpContent' could not be found (are you missing a using directive or an assembly reference?)" even if I have using System.Net.Http and even if I can see all methods and properties of the variable "content".Voroshilov
R
3

What you are after is a custom MediaTypeFormatter. It sounds like you wish to implement your own custom one to replace and existing or you're creating a new custom one all together depending what what Accept header you're expecting. Good news is you can swap out existing ones or come up with a new MediaType of you like. A couple places that will help get you started can be found here:

http://byterot.blogspot.com/2012/04/aspnet-web-api-series-part-5.html

http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters

Yes, I've actually done this in small part as I've swapped out some of the default formatter e.g. JSON with a faster one i.e. ServiceStack and it works great.

Recliner answered 29/10, 2012 at 20:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.