Ошибка маршрута Asp.net MVC 4

Я относительно новичок в MVC, но успешно построил на нем стандартный CRUD-сайт, управляемый пользователями, поэтому у меня есть некоторые основы. Я начал работать над тем, что я хотел бы стать приложением REST-FUL API, созданным с использованием MVC 4, и у меня возникла, как я уверен, проблема новичка в получении простого запроса на разрешение контроллера в этом новом приложении.

На простом тестовом ресурсе, предназначенном для поддержки операции POST, я получаю 404 вместо 202. Я искал на этом сайте решения проблем маршрутизации, пробовал несколько различных комбинаций аппаратного и параметризованного маршрута и значений по умолчанию, но пока не нашел ничего, что, как я подозреваю, должно быть легко исправить.

Обновить

Я также попытался изменить настройку конфигурации маршрута (см. Route Config #1 и #2 ниже), чтобы использовать MapHttpRoute() вместо MapRoute(). Это не имело никакого эффекта.

Оба эти веб-приложения размещаются в одной веб-роли Azure, настроенной как два разных сайта, которые прослушивают 2 разных порта. Проблема, которую я устраняю, связана с моей локальной машиной, поэтому при использовании эмулятора вычислений все URL-адреса начинаются с:

http://127.0.0.1:<port>/

Для клиента я использую RestSharp, вызываемый из приложения CRUD. Вот класс, используемый для заполнения тела запроса 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 Client

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
}

... вот две конфигурации маршрута, которые я пробовал:

Route Config #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 }
        );

    }

Route Config #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 ответа

Вам нужно будет использовать расширение " route. MapHttpRoute (", которое предназначено для регистрации маршрутов Api и предназначается для ApiControllers. В настоящее время вы используете MapRoute, который предназначен для контроллеров MVC.

Эта проблема, в частности, связана с запуском приложения rest в качестве веб-роли в эмуляторе вычислений Azure. Когда я просто щелкаю правой кнопкой мыши на приложении в VS и выбираю View in Browser, или устанавливаю его в качестве проекта по умолчанию и запускаю Debug->Start new Instance, я могу вызывать остальные API из браузера и получать ответы. Когда я запускаю приложение в качестве веб-роли в эмуляторе вычислений Azure, я получаю 404, как будто ни один из зарегистрированных маршрутов фактически не зарегистрирован.

Я мог бы опубликовать другой, другой, вопрос, связанный с эмулятором вычислений и приложениями WebAPI, но на данный момент не похоже, что есть проблема с моим кодом. Это может быть из-за конфигурации или из-за других проблем с системой / средой в моей настройке разработчика Azure или в эмуляторе вычислений есть какой-то дефект.

Другие вопросы по тегам