Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自定义404页面,带JSON,不带重定向_C#_Json_Asp.net Mvc_Api_Http Status Code 404 - Fatal编程技术网

C# 自定义404页面,带JSON,不带重定向

C# 自定义404页面,带JSON,不带重定向,c#,json,asp.net-mvc,api,http-status-code-404,C#,Json,Asp.net Mvc,Api,Http Status Code 404,我正在开发一个API,到目前为止,除了404页面(默认的ASP.NET404页面)之外,所有页面都返回JSON。我想更改它,以便它在404页面上也返回JSON。大概是这样的: {"Error":{"Code":1234,"Status":"Invalid Endpoint"}} 如果在Global.asax.cs文件中捕获404个错误并重定向到现有路由,则可以获得类似的效果: // file: Global.asax.cs protected void Application_Error(ob

我正在开发一个API,到目前为止,除了404页面(默认的ASP.NET404页面)之外,所有页面都返回JSON。我想更改它,以便它在404页面上也返回JSON。大概是这样的:

{"Error":{"Code":1234,"Status":"Invalid Endpoint"}}
如果在Global.asax.cs文件中捕获404个错误并重定向到现有路由,则可以获得类似的效果:

// file: Global.asax.cs
protected void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    if (ex is HttpException && ((HttpException)ex).GetHttpCode() == 404)
    {
        Response.Redirect("/CatchAll");
    }
}

// file: HomeController.cs
[Route("CatchAll")]
public ActionResult UnknownAPIURL()
{
    return Content("{\"Error\":{\"Code\":1234,\"Status\":\"Invalid Endpoint\"}}", "application/json");
}
但这会将302HTTP代码返回到新URL,这不是我想要的我想返回一个404 HTTP代码,代码体中包含JSON。我怎样才能做到这一点?

我尝试过的事情,但没有成功…

#1-覆盖默认错误页

我想也许我可以覆盖404处理程序中的默认错误页面。我这样试过:

// file: Global.asax.cs
protected void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    if (ex is HttpException && ((HttpException)ex).GetHttpCode() == 404)
    {
        Response.Clear();
        Response.StatusCode = 404;
        Response.TrySkipIisCustomErrors = true;
        Response.AddHeader("content-type", "application/json");
        Response.Write("{\"Error\":{\"Code\":1234,\"Status\":\"Invalid Endpoint\"}}");
    }
}
但它只是继续提供默认的ASP错误页面。顺便说一下,我根本没有修改我的
web.config
文件

#2-使用“一网打尽”的路线

我尝试在routes表的末尾添加一个“catch all”路由。我的整个路线配置现在看起来是这样的:

// file: RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapMvcAttributeRoutes();

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );

    routes.MapRoute(
        name: "NotFound",
        url: "{*data}",
        defaults: new { controller = "Home", action = "CatchAll", data = UrlParameter.Optional }
    );
}
但这也不行。如果我在
Application\u Error()
中放置一个断点,我可以看到它仍然以404错误代码结束。我不确定这是怎么可能的,因为“一网打尽”的路线应该是匹配的?但无论如何,它从来没有达到一网打尽的路线

#3-在运行时添加路由

我在另一个SO问题上看到了从错误处理程序中调用新路由的可能性。所以我试着:

// file: Global.asax.cs
protected void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    if (ex is HttpException && ((HttpException)ex).GetHttpCode() == 404)
    {
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Home");
        routeData.Values.Add("action", "CatchAll");

        Server.ClearError();
        Response.Clear();
        IController homeController = new HomeController();
        homeController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    }
}
但是,它会产生以下错误:

System.Web.Mvc.dll中发生“System.Web.HttpException”类型的异常,但未在用户代码中处理

其他信息:在controller
Myproject.Controllers.HomeController
上找不到公共操作方法“CatchAll”


控制器肯定有这种方法。我正在使用POST调用API,但是我已经尝试通过在方法之前添加
[HttpPost]
来专门为POST创建控制器,我仍然得到相同的错误。

我们在路由表的末尾有一个类似于

        config.Routes.MapHttpRoute(
            name: "NotImplemented",
            routeTemplate: "{*data}",
            defaults: new { controller = "Error", action = "notimplemented", data = UrlParameter.Optional });

我们在其中生成自定义响应。您可以在路由表中执行类似的操作。

我终于找到了一个有效的解决方案。从上面看基本上是#1,增加了一行:

// file: Global.asax.cs
protected void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    if (ex is HttpException && ((HttpException)ex).GetHttpCode() == 404)
    {
        Server.ClearError(); // important!!!
        Response.Clear();
        Response.StatusCode = 404;
        Response.TrySkipIisCustomErrors = true;
        Response.AddHeader("content-type", "application/json");
        Response.Write("{\"Error\":{\"Code\":1234,\"Status\":\"Invalid Endpoint\"}}");
    }
}

Server.ClearError()命令似乎非常重要。如果没有它,将返回常规ASP错误页,并且没有任何
响应。
方法对返回的数据有任何影响。

我尝试了这个方法,但这个新路由从未被命中。相反,
Application\u Error()
函数拦截调用。我将把这些信息添加到问题中。