web-dev-qa-db-ja.com

リモートサーバーがエラーを返しました:(415)Unsupported Media Type

WPF RESTfulクライアントからASP .NET MVC WebAPI 2ウェブサイトにテキストファイルをアップロードしようとしています。

クライアントコード

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://localhost:22678/api/Account/UploadFile?fileName=test.txt&description=MyDesc1");

request.Method = WebRequestMethods.Http.Post;
request.Headers.Add("Authorization", "Bearer " + tokenModel.ExternalAccessToken);  
request.ContentType = "text/plain";
request.MediaType = "text/plain";
byte[] fileToSend = File.ReadAllBytes(@"E:\test.txt");  
request.ContentLength = fileToSend.Length;

using (Stream requestStream = request.GetRequestStream())
{
      // Send the file as body request. 
      requestStream.Write(fileToSend, 0, fileToSend.Length);
      requestStream.Close();
}

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                        Console.WriteLine("HTTP/{0} {1} {2}", response.ProtocolVersion, (int)response.StatusCode, response.StatusDescription);

WebAPI 2コード

[HttpPost]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("UploadFile")]
public void UploadFile(string fileName, string description, Stream fileContents)
{
    byte[] buffer = new byte[32768];
    MemoryStream ms = new MemoryStream();
    int bytesRead, totalBytesRead = 0;
    do
    {
        bytesRead = fileContents.Read(buffer, 0, buffer.Length);
        totalBytesRead += bytesRead;

        ms.Write(buffer, 0, bytesRead);
    } while (bytesRead > 0);

   var data = ms.ToArray() ;

    ms.Close();
    Debug.WriteLine("Uploaded file {0} with {1} bytes", fileName, totalBytesRead);
}

だから..クライアントコードの下で私はその例外に直面しています

リモートサーバーがエラーを返しました:(415)Unsupported Media Type。

何が足りないのか手掛かりはありますか?

7
Developer

Radimによる上記の説明の+1 ...アクションのとおり、Web APIモデルバインディングは、パラメーターfileContentsが複合型であり、デフォルトでフォーマッターを使用してリクエスト本文のコンテンツを読み取ることを想定しています。 (fileNameおよびdescriptionパラメーターはstringタイプであるため、デフォルトではuriから取得されると想定されています)。

次のようなことを行って、モデルのバインドが行われないようにすることができます。

[HttpPost]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("UploadFile")]
public async Task UploadFile(string fileName, string description)
{
   byte[] fileContents = await Request.Content.ReadAsByteArrayAsync();

   ....
}

ところで、これをどうするつもりですかfileContents?ローカルファイルを作成しようとしていますか?もしそうなら、これを処理するより良い方法があります。

最後のコメントに基づいて更新

あなたができることの簡単な例

[HttpPost]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("UploadFile")]
public async Task UploadFile(string fileName, string description)
{
    Stream requestStream = await Request.Content.ReadAsStreamAsync();

    //TODO: Following are some cases you might need to handle
    //1. if there is already a file with the same name in the folder
    //2. by default, request content is buffered and so if large files are uploaded
    //   then the request buffer policy needs to be changed to be non-buffered to imporve memory usage
    //3. if exception happens while copying contents to a file

    using(FileStream fileStream = File.Create(@"C:\UploadedFiles\" + fileName))
    {
        await requestStream.CopyToAsync(fileStream);
    }

    // you need not close the request stream as Web API would take care of it
}
6
Kiran Challa

ContentType = "text/plain"を設定しており、この設定によってフォーマッタの選択が決まります。詳細は Media Formatters を確認してください。

抽出:

Web APIでは、メディアタイプによって、Web APIがHTTPメッセージ本文をシリアライズおよびデシリアライズする方法が決まります。 XML、JSON、フォームURLエンコードデータの組み込みサポートがあり、メディアフォーマッタを作成することで、追加のメディアタイプをサポートできます。

したがって、組み込みのtext/plainフォーマッタはありません。つまり、Unsupported Media Typeです。 link で説明されているように、コンテンツタイプをサポートされている組み込みのカスタムタイプに変更したり、カスタムタイプを実装したりできます。

14
Radim Köhler