14

新しいAsp.NetWebApiのリクエストからいくつかのデータを抽出しようとしています。私は次のようなハンドラー設定をしています:

public class MyTestHandler : DelegatingHandler
{
    protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        if (request.Content.IsFormData())
        {
            request.Content.ReadAsStreamAsync().ContinueWith(x => {
                var result = "";
                using (var sr = new StreamReader(x.Result))
                {
                    result = sr.ReadToEnd();
                }
                Console.Write(result);
            });
        }

        return base.SendAsync(request, cancellationToken);
    }
}

これは私のhttpリクエストです:

POST http://127.0.0.1/test HTTP/1.1
Connection: Keep-Alive
Content-Length: 29
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue
Host: 127.0.0.1

my_property=my_value

問題は、どのように情報を読み取ろうとしても、request.Content常に空であるということです。私はもう試した

request.Content.ReadAsStreamAsync
request.Content.ReadAsFormDataAsync
request.Content.ReadAs<FormDataCollection>

と同様

    [HttpGet,HttpPost]
    public string Index([FromBody]string my_property)
    {
        //my_property == null
        return "Test";
    }

動作する場合はなし。体からデータを取り出せません。Windows 7のIIS内でホストしており、Fiddlerを使用してリクエストを送信しています。私は何が間違っているのですか?

4

6 に答える 6

20

問題は、Web Apiでは、本文を1回しか読み取れないことです。リクエストのすべての詳細をログに記録し、本文を読み取っているHTTPモジュールを実行していました。

于 2012-08-17T16:32:11.083 に答える
7

醜いですが、最初のいじくり回しから、実際にはDelegatingHandlerのコンテンツを置き換えることができるようです...

protected override Task SendAsync(
          HttpRequestMessage request,
          CancellationToken cancellationToken)
      {                    
          Stream stream = new MemoryStream();

          request.Content.ReadAsStreamAsync().Result.CopyTo(stream);
          stream.Seek(0,SeekOrigin.Begin);

          // copy off the content "for later"
          string query = new StreamReader(stream).ReadToEnd();
          stream.Seek(0,SeekOrigin.Begin);

          // if further processing depends on content type
          // go ahead and grab current value
          var contentType = request.Content.Headers.ContentType;

          request.Content = new StreamContent(stream);
          request.Content.Headers.ContentType = contentType;

          return base.SendAsync(request, cancellationToken);
     }

これが良い形式か悪いか(悪いと思われる)かどうかはわかりませんが、....動作しているようで、リクエストヘッダーとコンテンツを「途中で」変更する必要がある人に推奨されるモデルに従います。 DelegatingHandler。

マイレージは大幅に異なる場合があります。

于 2012-10-06T13:10:18.987 に答える
6

私はbrmoreのコードに基づいて答えました。

この関数は、任意のハンドラーでコンテンツを安全に読み取ることができます

private string SafeReadContentFrom(HttpRequestMessage request)
{
     var contentType = request.Content.Headers.ContentType;
     var contentInString = request.Content.ReadAsStringAsync().Result;
     request.Content = new StringContent(contentInString);
     request.Content.Headers.ContentType = contentType;
     return contentInString;
}
于 2013-11-28T09:36:16.117 に答える
2

これは私のために働きます。

[HttpPost]
public IHttpActionResult Index(HttpRequestMessage request)
{
    var form = request.Content.ReadAsFormDataAsync().Result;
    return Ok();
}
于 2016-05-12T08:20:47.593 に答える
0

私は同じ問題を抱えていて、最終的にログにコンテンツを書き込まないことを選択しました。私はContent-TypeとContent-Lengthのログを記録しています。

ただし、可能な限りすべてのコンテンツをログに書き込むことは常に良い考えです。

しかし、現在WebApiではこれを達成できないようです。

于 2012-08-27T04:41:51.000 に答える
0

最初にプロバイダーを作成できます。MultipartMemoryStreamProvider() その後Request.Content.ReadAsMultipartAsync(provider); 次にコンテンツを読む

public async Task<IHttpActionResult> Post(int id, string type)
{
    // Check if the request contains multipart/form-data.
    if(!Request.Content.IsMimeMultipartContent("form-data"))
        return BadRequest("Unsupported media type");

    try
    {
        var azureManager = new AzureManager();
        var imageManager = new ImageManager();
        var provider = new MultipartMemoryStreamProvider();

        await Request.Content.ReadAsMultipartAsync(provider);

        var assets = new List<Asset>();
        foreach (var file in provider.Contents)
        {
            var stream = await file.ReadAsStreamAsync();
            var guid = Guid.NewGuid();
            string blobName = guid.ToString();

            await azureManager.UploadAsync(blobName, stream);

            var asset = new Asset
            {
                PropertyId = id,
                FileId = guid,
                FileName = file.Headers.ContentDisposition.FileName.Trim('\"').ToLower(),
                FileSize = file.Headers.ContentLength ?? 0,
                MimeType = file.Headers.ContentType.MediaType.ToLower()
            };

            if (type == "photos")
            {
                asset.Type = AssetType.Photo;

                // Resize and crop copies to 16:9
                using (MemoryStream thumb = imageManager.ResizeImage(stream, 320, 180))
                {
                    await azureManager.UploadAsync(blobName, thumb, BlobContainers.Thumbs);
                }
                using (MemoryStream photo = imageManager.ResizeImage(stream, 1024, 576))
                {
                    await azureManager.UploadAsync(blobName, photo, BlobContainers.Photos);
                }
            }
            else
                asset.AssumeType();

            assets.Add(asset);
        }

        db.Assets.AddRange(assets);
        await db.SaveChangesAsync();

        return Ok(new { Message = "Assets uploaded ok", Assets = assets });
    }
    catch (Exception ex)
    {
        return BadRequest(ex.GetBaseException().Message);
    }
}
于 2015-02-05T15:56:35.810 に答える