Asp.net MVC 4路由失败

时间:2013-05-16 20:10:08

标签: asp.net-mvc-4 routes restsharp azure-compute-emulator

我对MVC比较陌生,但是已经用它成功构建了一个标准的用户驱动的CRUD站点,所以我有一些基础知识。我开始研究我想成为一个用MVC 4构建的REST-ful api应用程序,我正在遇到一个新手问题,即在这个新应用程序中获得一个简单的请求来解析控制器。

在一个旨在支持POST操作的简单测试资源上,我得到404而不是202。我搜索了这个网站寻找路由问题的解决方案,尝试了许多不同的硬连线和参数化路由和默认值的组合,但还没有找到任何我怀疑必须是一个简单的解决方案。

更新

我还尝试更改路由配置设置(请参阅下面的Route Config#1和#2)以使用MapHttpRoute()而不是MapRoute()。这没有任何效果。

这些都是托管在单个Azure Web角色中的Web应用程序,配置为在两个不同端口上侦听的两个不同站点。我正在进行故障排除的问题是在我的本地计算机上,所以使用计算模拟器,所有的网址都以:

开头
http://127.0.0.1:<port>/

对于客户端,我正在使用从CRUD应用程序中调用的RestSharp。这是用于填充我正在调试的POST请求主体的类:

数据类

public class TestData
{
    public string Name { get; set; }
    public DateTime Date { get; set; }
    public Boolean IsTrue { get; set; }
}

...这是用于序列化数据并转换为字符串的代码。我知道RestSharp会为我序列化,但我还有其他特定于应用程序的原因,我自己正在进行序列化,我认为这与问题无关。如果事实证明与问题有关,我们可以去那里,但目前不在我的可疑名单上:

序列化方法

    private XmlDocument Serialize<T>( T theData )
    {
        XmlSerializer ser = new XmlSerializer( theData.GetType() );
        XmlDocument xml = new XmlDocument();

        using (MemoryStream stream = new MemoryStream())
        {
            ser.Serialize( stream, theData );
            stream.Flush();
            stream.Seek( 0, SeekOrigin.Begin );

            xml.Load( stream );
        }

        return xml;
    }

    private string GetStringFromXmlDocument( XmlDocument theDoc )
    {
        string result = null;

        using (var stringWriter = new StringWriter())
        using (var xmlTextWriter = XmlWriter.Create( stringWriter ))
        {
            theDoc.WriteTo( xmlTextWriter );
            xmlTextWriter.Flush();
            result = stringWriter.GetStringBuilder().ToString();
        }

        return result;
    }

...这里是使用数据类和上述方法的RestSharp客户端代码:

RestSharp客户端

XmlDocument theSerializedData = Serialize( new TestData
                                   {
                                       Date = DateTime.Now,
                                       IsTrue = false,
                                       Name = "Oscar"
                                   } );

string theDataString = GetStringFromXmlDocument(theSerializedData);

RestClient client = new RestClient("http://127.0.0.1:7080/rest/testing");

RestRequest request = new RestRequest( "tests", Method.POST );

request.AddParameter( "text/xml", theTestData, ParameterType.RequestBody );

IRestResponse response = client.Execute( request );

if (response.StatusCode == HttpStatusCode.OK)
{
    ; // Make a happy face
}
else
{
    ; // Make a sad face
}

...这是我尝试过的两种路线配置:

路由配置#1

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

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

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

    }

路由配置#2

    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
        name: "RestTest",
        routeTemplate: "rest/{controller}/{action}",
        defaults: new { controller = "Testing", action = "Tests" }
            );
    }

......这是控制器:

控制器

public class TestingController : ApiController
{
    [HttpPost]
    public void Tests(TestData theData)
    {
        bool isTru = theData.IsTrue;
    }
}

...这是从Fiddler捕获的原始请求(主机名替换为127.0.0.1):

Http请求

  POST http://127.0.0.1:7080/rest/testing/tests HTTP/1.1
  Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml
  User-Agent: RestSharp 104.1.0.0
  Content-Type: text/xml
  Host: 127.0.0.1:7080
  Content-Length: 243
  Accept-Encoding: gzip, deflate

  <?xml version="1.0"?>
  <TestData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Name>Oscar</Name>
    <Date>2013-05-16T11:50:50.1270268-07:00</Date>
    <IsTrue>false</IsTrue>
  </TestData>

......来自该服务的404响应的要点是:

404回复

The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.
Please review the following URL and make sure that it is spelled correctly.

Requested URL: /rest/testing/tests

[HttpException]: The controller for path '/rest/testing/tests' was not found or does not implement IController.
at System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
at System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName)
at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

2 个答案:

答案 0 :(得分:1)

你需要使用“routes。 MapHttpRoute (”扩展名,用于注册Api路由和目标ApiControllers。目前你使用的是用于MVC控制器的MapRoute。

答案 1 :(得分:0)

此问题特别与在Azure计算模拟器上将其余应用程序作为Web角色运行有关。当我在VS中右键单击应用程序并选择在浏览器中查看,或将其设置为默认项目并运行Debug-&gt;启动新实例时,我可以从浏览器调用其余API并获取响应。当我在Azure计算模拟器上将应用程序作为Web角色启动时,我得到404,就好像所有已注册的路由都没有实际注册一样。

我可能会发布与计算模拟器和WebAPI应用程序相关的另一个不同的问题,但此时我的代码似乎没有问题。我的Azure开发设置可能是配置或其他一些系统/环境问题,或者计算模拟器中存在一些缺陷。