practices - Todas las solicitudes a ASP.NET Web API devuelven error 404
asp net webapi (3)
Gracias al comentario de Kiran Challa y al código fuente de esta respuesta , pude descubrir que ReportViewer 11 assembly
un ensamblaje (el ReportViewer 11 assembly
para SQL Server Reporting Services) en el servidor de producción.
Aunque no ApiController
ningún ApiController
en este conjunto, parece que no se encuentran los controladores en ensamblajes, en este caso el ensamblado de mi proyecto web, que hacen referencia al ensamblaje que falta.
Aparentemente, este comportamiento está relacionado con este fragmento de código del origen DefaultHttpControllerTypeResolver
la API web :
List<Type> result = new List<Type>();
// Go through all assemblies referenced by the application
// and search for types matching a predicate
ICollection<Assembly> assemblies = assembliesResolver.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
Type[] exportedTypes = null;
if (assembly == null || assembly.IsDynamic)
{
// can''t call GetExportedTypes on a dynamic assembly
continue;
}
try
{
exportedTypes = assembly.GetExportedTypes();
}
catch (ReflectionTypeLoadException ex)
{
exportedTypes = ex.Types;
}
catch
{
// We deliberately ignore all exceptions when building the cache. If
// a controller type is not found then we will respond later with a 404.
// However, until then we don''t know whether an exception at all will
// have an impact on finding a controller.
continue;
}
if (exportedTypes != null)
{
result.AddRange(exportedTypes.Where(x => IsControllerTypePredicate(x)));
}
}
No sé si tiene que ser así y no estoy muy convencido por el comentario en el código, pero este catch ... continue
bloqueando es bastante silencioso sobre un posible problema y me tomó una gran cantidad de tiempo y frustración para encontrarlo. Incluso sabía que ReportViewer
aún no estaba instalado. Traté de instalarlo y los ensamblajes dependientes, pero fue bloqueado por otro proceso en ejecución en el servidor, así que decidí posponer la instalación hasta que pude contactar al administrador y centrarme primero en las pruebas MVC y WebAPI. ¡Gran error! Sin el fragmento de código de depuración de Kiran, nunca tuve la idea de que la existencia de un ReportViewer.dll
pudiera tener algo que ver con la resolución del tipo de controlador.
En mi opinión, hay un margen de mejora para el desarrollador promedio como yo que no tiene un conocimiento más profundo sobre el funcionamiento interno de la API web.
Después de instalar el ReportViewer.dll
faltante, el problema desapareció.
Aquí hay preguntas sobre el mismo síntoma que podría tener el mismo motivo:
- Todos los controladores API web ASP.NET devuelven 404
- .Net Web API No se encontró ningún recurso HTTP que coincida con el URI de solicitud
- http://forums.asp.net/t/1861082.aspx/1?All+controllers+break+404+whenever+I+publish+to+Azure
Editar
He enviado una solicitud de mejora en CodePlex:
http://aspnetwebstack.codeplex.com/workitem/1075
Editar 2 (11 de agosto de 2013)
El problema se ha corregido para WebAPI v5.0 RC. Consulte el enlace de arriba al sitio de trabajo y su sección de comentarios para más detalles.
Tengo un sitio web ASP.NET MVC 4 que incluye API web. El sitio está desarrollado y probado con Visual Studio 2012 y .NET 4.5 en Windows 8 con IIS Express como servidor web. En este entorno de desarrollo, todo funciona.
Ahora está implementado en un servidor de Windows 2008 R2 (SP1) con IIS 7.5. .NET 4.0 y 4.5 están instalados. El grupo de aplicaciones se ejecuta con .NET 4.0 en modo de canalización integrada.
En este entorno de producción, el sitio web de MVC funciona, pero Web API no. Para cada solicitud, no importa si GET o POST recibo un error 404. Si solo ingreso una URL de la API web en el navegador (IE 9 se abre localmente en el servidor) para ejecutar una solicitud GET, obtengo una página 404. Si emite una solicitud POST desde una aplicación de cliente Web API, también recibo un 404 y el mensaje:
No se encontró ningún recurso HTTP que coincida con el URI de solicitud
También creé un sitio web de prueba con MVC 4 y API web y lo implementé en el mismo servidor y funciona la API web. Los ensamblados Web API y MVC tienen el mismo número de versión en ambos proyectos.
Además, he agregado Web API Debugger de ruta a la aplicación. Si uso una ruta válida como http://myserver/api/order/12
obtengo el siguiente resultado:
Para mí, esto significa que la plantilla de ruta correcta Api/{Controller}/{Id}
se ha encontrado y procesado correctamente en un controlador Order
and Id=12
. El controlador (derivado de ApiController
) existe en el conjunto web donde también están todos los controladores MVC.
Sin embargo, no sé qué significa el estado 000
y por qué no se muestra la sección " ApiController
ruta" (que normalmente es el caso incluso si el ensamblaje no contiene un solo ApiController
, ver capturas de pantalla en la página vinculada más arriba) . De alguna manera parece que no se encuentra ni se busca ni se busca ApiController
o la búsqueda falla silenciosamente.
Los archivos de registro de IIS no muestran nada útil. Cambiar las diversas configuraciones del grupo de aplicaciones y usar el mismo grupo de aplicaciones para la prueba y la aplicación real no ayudó.
Actualmente estoy en el proceso de eliminar las "características", las configuraciones, los ensamblajes de terceros, etc. de la aplicación para reducirla al tamaño pequeño de la aplicación de prueba y espero que en algún momento empiece a funcionar.
¿Alguien tiene una idea de lo que podría ser el problema? También es muy bienvenida cualquier idea de depuración o registro para encontrar el motivo.
Editar
Gracias a la sugerencia de Darrel Miller en los comentarios a continuación, he integrado Tracing para ASP.NET Web Api .
Para la URL de solicitud (GET) http://myserver/api/order/12
obtengo lo siguiente:
- En entorno de desarrollo, exitoso (en forma abreviada):
Mensaje:
http://localhost:50020/api/order/12
; Categoría: System.Web.Http.RequestSelección e instanciación del controlador ...
Operador: DefaultHttpControllerSelector; Operación: SelectController; Mensaje: Ruta = "controlador: orden, id: 12"; Categoría: System.Web.Http.Controllers
Operador: DefaultHttpControllerSelector; Operación: SelectController; Mensaje: orden; Categoría: System.Web.Http.Controllers
Operador: HttpControllerDescriptor; Operación: CreateController; Mensaje: Categoría: System.Web.Http.Controllers
Operador: DefaultHttpControllerActivator; Operación: Crear; Mensaje: Categoría: System.Web.Http.Controllers
Operador: DefaultHttpControllerActivator; Operación: Crear; Mensaje: MyApplication.ApiControllers.OrderController; Categoría: System.Web.Http.Controllers
La selección de acciones, el enlace de parámetros y la invocación de acciones siguen ...
La negociación del contenido y el formato para el resultado ...
Operador: DefaultContentNegotiator; Operación: Negociar; Mensaje: Typ = "String" ... más
Desechando el controlador ...
Operador: OrderController; Operación: Eliminar; Mensaje: Categoría: System.Web.Http.Controllers
- En el entorno de producción, no exitoso (en forma abreviada):
Mensaje:
http://myserver/api/order/12
; Categoría: System.Web.Http.RequestOperador: DefaultHttpControllerSelector; Operación: SelectController; Mensaje: Ruta = "controlador: orden, id: 12"; Categoría: System.Web.Http.Controllers
Falta la parte completa de la activación del controlador, la selección de acción, el enlace de parámetros, la invocación de acciones y sigue inmediatamente la negociación de contenido y el formateo del mensaje de error :
Operador: DefaultContentNegotiator; Operación: Negociar; Mensaje: Type = "HttpError" ... más
Grandes recursos en esta respuesta, sin embargo, obtuve un 404 por lo que resultó ser una razón bastante tonta:
- Creé un instalador de WiX para mi proyecto API
- Lo instalé en una VM de prueba (máquina virtual)
- Solicitado por el URI que la API debería servir
- ¡EXPLOSIÓN! 404 :(
Resultó que había omitido el empaquetado y la implementación de Global.asax en la raíz del directorio virtual en mi implementación. Agregando esto aquí para el beneficio de Goofies como yo :)
Tuve el mismo problema en un servidor remoto, pero cuando ejecuto en un servidor local funciona bien.
Mi solución fue:
<system.webServer>
<modules>
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0"
type="System.Web.Routing.UrlRoutingModule" preCondition="" />
</modules>
</system.webServer>
Espero que esto funcione para ti.