1

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

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

更新

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

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

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)
4

2 回答 2

1

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

于 2013-05-16T22:20:45.233 回答
0

此问题专门与在 Azure 计算模拟器上将其余应用程序作为 Web 角色运行有关。当我只需在 VS 中右键单击应用程序并选择在浏览器中查看,或将其设置为默认项目并运行 Debug->Start new Instance,我就可以从浏览器调用其余 API 并获得响应。当我在 Azure 计算模拟器上将应用程序作为 Web 角色启动时,我得到了 404,好像没有任何已注册的路由实际上被注册。

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

于 2013-05-17T19:29:33.667 回答