8

メモリ内テストでASP.NETWebAPIコントローラーをテストすると、「内部サーバーエラー」(ステータスコード500)が発生します。

[TestFixture]
public class ValuesControllerTest
{
    private HttpResponseMessage response;

    [TestFixtureSetUp]
    public void Given()
    {
        var config = new HttpConfiguration
        {
            IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always
        };

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { controller = typeof(ValuesController).Name.Replace("Controller", string.Empty), id = RouteParameter.Optional }
        );

        //This method will cause internal server error but NOT throw any exceptions
        //Remove this call and the test will be green
        ScanAssemblies();

        var server = new HttpServer(config);
        var client = new HttpClient(server);
        response = client.GetAsync("http://something/api/values/5").Result;
        //Here response has status code 500

    }

    private void ScanAssemblies()
    {
        PluginScanner.Scan(".\\", IsApiController);
    }

    private bool IsApiController(Type type)
    {
        return typeof (ApiController).IsAssignableFrom(type);
    }

    [Test]
    public void Can_GET_api_values_5()
    {
        Assert.IsTrue(response.IsSuccessStatusCode);
    }
}

public static class PluginScanner
{
    public static IEnumerable<Type> Scan(string directoryToScan, Func<Type, bool> filter)
    {
        var result = new List<Type>();
        var dir = new DirectoryInfo(directoryToScan);

        if (!dir.Exists) return result;

        foreach (var file in dir.EnumerateFiles("*.dll"))
        {
            result.AddRange(from type in Assembly.LoadFile(file.FullName).GetTypes()
                            where filter(type)
                            select type);
        }
        return result;
    }
}

.Net例外がスローされたときに中断するようにVisualStudioを構成しました。コードはどの例外でも停止せず、応答で例外の詳細を見つけることもできません。

「内部サーバーエラー」の原因を確認するにはどうすればよいですか?

4

3 に答える 3

12

例外はResponse.Contentにあります

if (Response != null && Response.IsSuccessStatusCode == false)
{
    var result = Response.Content.ReadAsStringAsync().Result;
    Console.Out.WriteLine("Http operation unsuccessful");
    Console.Out.WriteLine(string.Format("Status: '{0}'", Response.StatusCode));
    Console.Out.WriteLine(string.Format("Reason: '{0}'", Response.ReasonPhrase));
    Console.Out.WriteLine(result);
}
于 2012-05-23T10:53:29.237 に答える
4

次のようになるようにルートを追加する必要があります。

        var config = new HttpConfiguration()
        {
            IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always
        };

        config.Routes.MapHttpRoute(
            name: "default",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { controller = "Home", id = RouteParameter.Optional });

        var server = new HttpServer(config);
        var client = new HttpClient(server);

        HttpResponseMessage response = client.GetAsync("http://somedomain/api/product").Result;

ところで、最新のビットでは、予想どおり 404 Not Found が表示されます。

ヘンリク

于 2012-05-22T21:36:44.967 に答える
1

あなたはすでに答えを見つけているようですが、それは私にとっては十分ではなかったので、私の問題を抱えている他の人のためにこれを追加したいと思います.

まず、新しい MVC 4 フォーマッタの問題のようです。エラー ポリシー フラグの設定 (IncludeErrorDetailPolicy、CustomErrors など) は機能しません。これらのフォーマッタはそれらを無視し、「内部サーバー エラー」500 を返し、空にします。

最終的にフォーマッターをオーバーロードし、エラーの応答をチェックすることで、これを見つけました。

public class XmlMediaTypeFormatterWrapper : XmlMediaTypeFormatter
{
    public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext transportContext)
    {
        var ret = base.WriteToStreamAsync(type, value, stream, contentHeaders, transportContext);
        if (null != ret.Exception)
            // This means there was an error and ret.Exception has all the error message data you would expect, but once you return below, all you get is a blank 500 error...

        return ret;
    } 
}

今のところ、単に ret.Exception を探してキャプチャする Xml および Json フォーマッタ ラッパーを使用しているので、少なくとも 500 が発生した場合にデータを取得できます。Task.Exception は既に設定されており、これが例外を渡すために必要なすべてであるため、エラーを実際にhtml応答に表示するエレガントな方法を実際に見つけることができませんでした。

于 2012-08-14T19:45:56.517 に答える