カスタムMediaTypeFormatterでは奇妙な動作が発生していますが、Owin Self-hosted WebApiでのみ発生します。カスタム非同期MediaTypeFormatterが返され、閉じられたストリームにアクセスできない
IISでホストされている標準.NET WebApiプロジェクトでは、同じフォーマッタが正常に動作します。
FormatterのCanWriteType
が複数回呼び出されています。例外ロガーは例外を除いて発砲していますCannot access a closed stream.
洞察力は非常に役に立ちます!このフォーマッタの非同期性を取り除くと、正常に動作するので、おそらく奇妙なスレッド問題です。可能であれば、非同期フォーマッタを使用して、BufferedMediaTypeFormatter
を使用しないでください。
スタックトレース:
at System.IO.__Error.StreamIsClosed()
at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc)
at System.Net.Http.HttpContent.<>c__DisplayClass21_0.<LoadIntoBufferAsync>b__0(Task copyTask)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Owin.HttpMessageHandlerAdapter.<BufferResponseContentAsync>d__13.MoveNext()
Startup.cs:
namespace ConsoleApplication1
{
public class TraceExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
Trace.TraceError(context.ExceptionContext.Exception.ToString());
}
}
public class Startup
{
// This code configures Web API. The Startup class is specified as a type
// parameter in the WebApp.Start method.
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
// Add in a simple exception tracer so we can see what is causing the 500 Internal Server Error
config.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());
// Add in the custom formatter
config.Formatters.Add(new JsonFhirAsyncFormatter());
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Add(new JsonFhirAsyncFormatter());
appBuilder.UseWebApi(config);
}
}
}
フォーマッタ:
namespace ConsoleApplication1
{
public class JsonFhirAsyncFormatter : MediaTypeFormatter
{
public JsonFhirAsyncFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json+fhir"));
}
public override bool CanWriteType(Type type)
{
return true;
}
public override bool CanReadType(Type type)
{
return false;
}
public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
using (StreamWriter streamwriter = new StreamWriter(writeStream))
{
await streamwriter.WriteAsync("{\"test\":\"test\"}");
}
}
}
}
コントローラー:
namespace ConsoleApplication1.Controllers
{
[RoutePrefix("test")]
public class TestController : ApiController
{
[HttpGet]
[Route("")]
public async Task<string> Test()
{
// Eventually this will using an await method
return "test";
}
}
}
の
のProgram.cs:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
WebApp.Start<Startup>("http://localhost:9000");
Console.ReadLine();
}
}
}
あなたが達成するために何をしようとしているとして実装されている
...あなたのコードに基づいて、あなたは車輪を再発明しようとしているようです...あなたは、OWINの自己ホストWeb APIを使って、それを試してみてください。 – Hackerman
私はOWINを使ってWeb apiをホストしています。だからこそ、私は「Owin Self-hosted WebApiだけで」と言ったのです。これはOWINを使用しています。この質問は、OwinスタートアップクラスであるStartup.csクラスのカスタムMediaTypeFormatterでのスレッド問題に関するものです。私は具体的にOWINの指示に従ってhttps://www.asp.net/web-api/overview/hosting-aspnet-web-api/use-owin-to-self-host-web-apiにアクセスし、サンプルプロジェクトを作成しました。問題が何であるかを示します。 –
ええ、私の悪い....私はあなたの質問の真ん中まで読んだだけです...確かに、その記事は2013年からの日付です、そして時代遅れのコードかもしれません...私はこの1つを試して、魅力のように動作します..コードはgithubでも利用できます:http://codeopinion.com/self-host-asp-net-web-api/ – Hackerman