Có cách nào để buộc API Web ASP.NET trả lại văn bản thuần túy không?


125

Tôi cần nhận được phản hồi bằng văn bản thuần túy từ bộ điều khiển API Web ASP.NET.

Tôi đã thử thực hiện một yêu cầu Accept: text/plainnhưng dường như không thực hiện được. Bên cạnh đó, yêu cầu là bên ngoài và ngoài tầm kiểm soát của tôi. Những gì tôi sẽ thực hiện là bắt chước cách ASP.NET cũ:

context.Response.ContentType = "text/plain";
context.Response.Write("some text);

Có ý kiến ​​gì không?

EDIT, giải pháp : Dựa trên câu trả lời của Aliostad, tôi đã thêm trình định dạng văn bản WebAPIContrib , khởi tạo nó trong Application_Start:

  config.Formatters.Add(new PlainTextFormatter());

và bộ điều khiển của tôi đã kết thúc một cái gì đó như:

[HttpGet, HttpPost]
public HttpResponseMessage GetPlainText()
{
  return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, "Test data", "text/plain");
}

Câu trả lời:


231

Hmmm ... Tôi không nghĩ bạn cần tạo một trình định dạng tùy chỉnh để làm cho công việc này. Thay vào đó trả lại nội dung như thế này:

    [HttpGet]
    public HttpResponseMessage HelloWorld()
    {
        string result = "Hello world! Time is: " + DateTime.Now;
        var resp = new HttpResponseMessage(HttpStatusCode.OK);
        resp.Content = new StringContent(result, System.Text.Encoding.UTF8, "text/plain");
        return resp;
    }

Điều này làm việc cho tôi mà không cần sử dụng một định dạng tùy chỉnh.

Nếu bạn rõ ràng muốn tạo đầu ra và ghi đè thương lượng nội dung mặc định dựa trên các tiêu đề Chấp nhận bạn sẽ không muốn sử dụng Request.CreateResponse() vì nó buộc loại mime.

Thay vào đó rõ ràng tạo một cái mới HttpResponseMessagevà gán nội dung bằng tay. Ví dụ trên sử dụng StringContentnhưng có khá nhiều lớp nội dung khác có sẵn để trả về dữ liệu từ các kiểu / cấu trúc dữ liệu .NET khác nhau.


1
Thực tế đây là giải pháp tôi đã thực hiện vì API của tôi sẽ trả về các đối tượng JSON cho 99% tất cả các phương thức, chỉ một số (rất ít) phương thức sẽ cần phản hồi chuỗi đơn giản (và đối với nhiều người tôi sử dụng MemoryStream để trả về dữ liệu trực tiếp trong phản hồi vì vậy đó không phải là vấn đề.) Chỉ trong 2 hoặc 3 phương thức tôi mới trả về chuỗi .NET và nó được trả về dưới dạng chuỗi JSON. Câu trả lời của bạn, IMHO, là phản hồi KISS cho vấn đề này (mặc dù nó không phải là 100% DRY, nhưng tôi chỉ viết một phương thức mở rộng để xâu chuỗi để làm điều đó ... :-) Nice!) StringContent rất hay. Cảm ơn bạn.
Lâu đài

Có một số lớp XXXContent tùy chỉnh để tạo các loại nội dung cụ thể làm cho loại điều này trở nên khá dễ dàng.
Rick Strahl

Tôi thấy phản ứng chính xác với phương pháp này. Tuy nhiên, httpContext.C hiện tại là null. Bất cứ ý tưởng về điều này?
Nachiket Mehta

@JavascriptEnthusiast - HttpContext.C hiện tại không có khả năng vì bạn tự lưu trữ hoặc chạy qua ngăn xếp OWin mà không có đường dẫn System.Web. Không liên quan đến giải pháp này mặc dù.
Rick Strahl

15

Nếu bạn chỉ tìm kiếm một trình định dạng văn bản / văn bản đơn giản mà không cần thêm các phụ thuộc bổ sung, thì điều này sẽ thực hiện thủ thuật.

public class TextPlainFormatter : MediaTypeFormatter
{
    public TextPlainFormatter()
    {
        this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
    }

    public override bool CanWriteType(Type type)
    {
        return type == typeof(string);
    }

    public override bool CanReadType(Type type)
    {
        return type == typeof(string);
    }

    public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext transportContext)
    {
        return Task.Factory.StartNew(() => {
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(value);
            writer.Flush();
        });
    }

    public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
    {
        return Task.Factory.StartNew(() => {
            StreamReader reader = new StreamReader(stream);
            return (object)reader.ReadToEnd();
        });
    }
}

Đừng quên thêm nó vào cấu hình api web toàn cầu của bạn.

config.Formatters.Add(new TextPlainFormatter());

Bây giờ bạn có thể truyền các đối tượng chuỗi cho

this.Request.CreateResponse(HttpStatusCode.OK, "some text", "text/plain");

12
  • Hãy cẩn thận không sử dụng ngữ cảnh trong ASP.NET Web API nếu không sớm muộn bạn cũng sẽ xin lỗi. Bản chất không đồng bộ của API Web ASP.NET làm cho việc sử dụng HttpContext.Currentmột trách nhiệm pháp lý.
  • Sử dụng một trình định dạng văn bản đơn giản và thêm vào trình định dạng của bạn. Có hàng tá trong số họ xung quanh. Bạn thậm chí có thể viết của bạn một cách dễ dàng. WebApiContrib có một.
  • Bạn có thể buộc nó bằng cách thiết lập các tiêu đề kiểu nội dung trên httpResponseMessage.Headersđể text/plaintrong điều khiển của bạn với điều kiện bạn đã đăng ký đồng bằng định dạng văn bản.

Đừng lo lắng, tôi không ngụ ý hay sử dụng đối tượng HttpContext, tôi chỉ thêm nó để minh họa cách người ta sẽ làm điều đó trong ASP.NET cổ điển
Magnus Johansson

Chà, waddayledge, tôi đã có tham chiếu WebAPIContrib, đôi khi nó đơn giản.
Magnus Johansson

@Magnus Chắc chắn rồi. Tôi thực tế đã thay đổi từ ngữ sau khi tôi đọc những gì tôi đã viết. Nhưng đọc một câu trả lời khác làm tôi căng thẳng điểm đầu tiên.
Aliostad

Bạn đang nói không sử dụng HttpContext.C hiện tại, các lựa chọn thay thế là gì?
surya

@spiderdevil vâng, đó hoàn toàn là những gì tôi đang nói. Bạn không cần nó, chuyển yêu cầu / phản hồi / cấu hình trực tiếp.
Aliostad


6

Khi Chấp nhận: văn bản / thuần túy không hoạt động, thì không có định dạng đã đăng ký cho các loại mime văn bản.

Bạn có thể đảm bảo rằng không có trình định dạng cho loại mime được chỉ định bằng cách lấy danh sách tất cả các trình định dạng được hỗ trợ từ cấu hình dịch vụ.

Tạo một trình định dạng loại phương tiện rất đơn giản hỗ trợ các loại mime văn bản.

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


Ước gì tôi cũng có thể chấp nhận câu trả lời của bạn, câu trả lời được chấp nhận đã cứu tôi những rắc rối khi viết định dạng của riêng tôi. Ít nhất +1.
Magnus Johansson

0

Một tiện ích mở rộng như sau có thể giảm số lượng dòng và làm đẹp mã của bạn:

public static class CommonExtensions
{
    public static HttpResponseMessage ToHttpResponseMessage(this string str)
    {
        var resp = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent(str, System.Text.Encoding.UTF8, "text/plain")
        };

        return resp;
    }
}


Bây giờ bạn có thể sử dụng phần mở rộng được xác định trong Web API:

public class HomeController : ApiController
{
    [System.Web.Http.HttpGet]
    public HttpResponseMessage Index()
    {
        return "Salam".ToHttpResponseMessage();
    }
}


Bằng cách định tuyến, {DOMAIN}/api/Home/Indexbạn có thể thấy văn bản đơn giản sau:

MyPlainTextResponse


Đừng lãng phí không gian tên chuỗi với những thứ không liên quan đến chuỗi.
Rambalac
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.