WebApi {„komunikat”: „wystąpił błąd”} w usługach IIS7, a nie w IIS Express

171

Pracuję z ASP.NET MVC 4 WebApi i świetnie się bawię, uruchamiając go na moim lokalnym komputerze w IIS Express. Skonfigurowałem IIS Express do obsługi komputerów zdalnych, więc inni w mojej firmie używają mojego komputera jako naszego serwera internetowego.

Po uznaniu, że nie jest to optymalne rozwiązanie, zdecydowaliśmy się umieścić WebApi na zdalnym serwerze po zainstalowaniu .NET 4.5. Kiedy używam fiddlera i wysyłam POST do kontrolera na mojej lokalnej maszynie, zwraca poprawną odpowiedź, ale kiedy zmieniam domenę na serwer sieciowy z IIS7, ten sam POST zwraca tajemniczy

{"message": "wystąpił błąd"}

wiadomość. Czy ktoś ma pojęcie, co może się dziać?

nsg
źródło
2
Jaki jest kod stanu HTTP w odpowiedzi o błędzie? Jeśli jest to 500, jest bardzo prawdopodobne, że konfiguracja witryny / aplikacji jest nieprawidłowa dla komputera zdalnego z usługami IIS 7. Utwórz prosty plik HTML na komputerze zdalnym, przejrzyj go na komputerze zdalnym, jeśli to możliwe, aby upewnić się, że można go wyświetlić, a następnie spróbuj uderzyć go z komputera, aby sprawdzić, czy się powiedzie, czy nie.
Sixto Saez
To błąd 500. Dziękuję za sugestię, ale domyślna strona index.html udostępniana przez WebApi działa. Powinienem również dodać, że niektóre usługi sieciowe API działają, a inne nie, podczas gdy wszystkie z nich działają na moim komputerze lokalnym.
nsg
2
Musisz włączyć śledzenie żądań usług IIS, aby uzyskać więcej szczegółowych informacji, gdy pojawi się błąd 500. Błąd 500 zwykle pojawia się przed uruchomieniem routingu internetowego interfejsu API, ale wydaje mi się, że można go wyzwolić przez coś, co robi twój kod. Przyjrzyj się dziennikowi śledzenia usług IIS i zobacz, czy zawiera on jakieś wskazówki.
Sixto Saez
1
Możesz uzyskać od serwera bardziej szczegółowe informacje o błędzie w swojej odpowiedzi, inicjując żądanie z przeglądarki na samym serwerze (np. Używając sesji pulpitu zdalnego).
Jon Schneider,

Odpowiedzi:

268

Problem polegał na braku zależności, której nie było na serwerze, ale na moim komputerze lokalnym. W naszym przypadku był to plik dll Devart.Data.Linq.

Aby uzyskać tę odpowiedź, włączyłem śledzenie IIS dla 500 błędów. To dało trochę informacji, ale naprawdę pomocne było ustawienie w pliku web.config <system.web><customErrors mode="Off"/></system.web>To wskazało na brakującą zależność ładowaną dynamicznie. Po dodaniu tej zależności i poleceniu jej lokalnego skopiowania serwer zaczął działać.

nsg
źródło
33
Wygląda na to, że interfejs WebAPI zastąpi prawdziwą odpowiedź {"message": "wystąpił błąd"} za każdym razem, gdy kod odpowiedzi HTTP ma wartość 500, a niestandardowe błędy są włączone. Dzięki za wskazówkę.
Paul Suart,
4
Świetna sugestia dotycząca ustawienia trybu customErrors. Jestem zdziwiony zmianą, która miała wpływ na wyniki tego rodzaju błędów.
Dewi Rees
1
możesz również ustawić to na, mode="RemoteOnly"a jeśli uruchomisz stronę w przeglądarce internetowej na serwerze, zobaczysz również błędy bez narażania bezpieczeństwa, jeśli reszta witryny jest dostępna z zewnątrz
Simon_Weaver.
Jakieś sugestie, jak uzyskać tego rodzaju szczegółowe informacje o błędach, gdy zmiana tego ustawienia nie jest możliwa (np. Błędy są wyłączone na poziomie maszyny, ponieważ część API jest hostowana na serwerze zgodnym z PCI)? Próbowałem skonfigurować Elmah, ale niestety nic nie rejestruje.
RubyHaus
To jest najlepsze podejście, daje wystarczająco dużo informacji na temat takiej ogólnej metody.
DanielV,
97

Gruntownie:

Użyj IncludeErrorDetailPolicyzamiast tego, jeśli CustomErrorsnie rozwiąże tego za Ciebie (np. Jeśli jesteś stosem ASP.NET> 2012):

GlobalConfiguration.Configuration.IncludeErrorDetailPolicy 
= IncludeErrorDetailPolicy.Always;

Uwaga: bądź ostrożny, zwracając szczegółowe informacje o błędzie, może ujawnić poufne informacje „hakerom”. Zobacz komentarz Simona do tej odpowiedzi poniżej.

Wersja TL; DR

Mnie CustomErrorsnie pomogło. Było już ustawione Off, ale nadal otrzymałem tylko marną an error has occurredwiadomość. Wydaje mi się, że przyjęta odpowiedź pochodzi z okresu sprzed 3 lat, co w dzisiejszych czasach jest od dawna. Używam Web API 2 i ASP.NET 5 (MVC 5), a Microsoft odszedł od strategii CustomErrorsopartej tylko na IIS, podczas gdy jest old skool IIS;).

W każdym razie miałem problem z produkcją, którego nie miałem lokalnie. A potem stwierdziłem, że nie widzę błędów na karcie Sieć w Chrome, tak jak na moim komputerze deweloperskim. W końcu udało mi się go rozwiązać, instalując Chrome na moim serwerze produkcyjnym, a następnie przeglądając aplikację na samym serwerze (np. Na „localhost”). Następnie pojawiły się bardziej szczegółowe błędy ze śladami stosu i wszystkim.

Dopiero potem znalazłem ten artykuł od Jimmy'ego Bogarda (Uwaga: Jimmy to pan AutoMapper! ). Zabawne jest to, że jego artykuł jest również z 2012 roku, ale w nim już wyjaśnia, że CustomErrorsto już nie pomaga, ale MOŻESZ zmienić 'Szczegóły błędu', ustawiając inną IncludeErrorDetailPolicyw globalnej konfiguracji WebApi (np. WebApiConfig.cs):

GlobalConfiguration.Configuration.IncludeErrorDetailPolicy 
= IncludeErrorDetailPolicy.Always;

Na szczęście wyjaśnia również, jak to skonfigurować, że webapi (2) SŁUCHA twoich CustomErrorsustawień. To całkiem rozsądne podejście, które pozwala wrócić do 2012 roku: P.

Uwaga: Wartość domyślna to „LocalOnly”, co wyjaśnia, dlaczego udało mi się rozwiązać problem w sposób opisany przeze mnie przed znalezieniem tego wpisu. Ale rozumiem, że nie każdy może po prostu zdalnie sterować produkcją i uruchamiać przeglądarkę (wiem, że przeważnie nie mogłem, dopóki nie zdecydowałem się przejść na freelancera i DevOps).

Bart
źródło
2
Teraz to działa. Dziękuję Ci! Mam kilka testów typu in-memory-Integration-owin, które kończą się niepowodzeniem na serwerze kompilacji, ale nie lokalnie. Dzięki temu ustawieniu w mojej klasie startowej, być może będę miał szansę dowiedzieć się, dlaczego.
Thomas Eyde,
Wygląda na to, że ustawienie customError współpracuje z WebApi 2, gdy jest hostowane w usługach IIS przez Microsoft.AspNet.WebApi.WebHost. Pakiety są w wersji 5.2.3, czyli stosu ASP.NET dawno po 2012 roku. Po ustawieniu go na Off, interfejs API sieci Web przełącza się z błędów ogólnych na bardziej szczegółowe, zawierające stos wywołań itp.
Tom
4
Zachowaj ostrożność, ustawiając to ustawienie, ponieważ może to ujawnić poufne informacje „hakerom”. Często robię szybki hack, na przykład, if (DateTime.Now < new DateTime(2017, 6, 22)) { .... }aby ustawić taką opcję. Następnie mogę przetestować go w środowisku produkcyjnym, a jutro w magiczny sposób powróci do normalnego zachowania, jeśli zapomnę go wyłączyć.
Simon_Weaver,
36

Żadna z pozostałych odpowiedzi nie działała dla mnie.

To zrobiło: (w Startup.cs)

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();

        WebApiConfig.Register(config);

        // Here: 
        config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
    }
}

(lub możesz umieścić go w WebApiConfig.cs):

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        // Here: 
        config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
    }
}
samneric
źródło
Tak! To było dla mnie jedyne działające rozwiązanie na Mono / Linux.
Robert II
Pomogło mi to w przypadku wersji produkcyjnej aplikacji udostępnianej wewnętrznie w usługach IIS i Windows Server.
Paul Carlton,
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; pomogło mi znaleźć, że
zwracam
12

Zawsze dochodzę do tego pytania, gdy napotykam błąd w środowisku testowym i przypominam sobie: „Robiłem to już wcześniej, ale mogę to zrobić bezpośrednio w pliku web.config bez konieczności modyfikowania kodu i ponownego wdrażania w środowisku testowym , ale wymaga 2 zmian ... co to było znowu? ”

Dla przyszłego odniesienia

<system.web>
   <customErrors mode="Off"></customErrors>
</system.web>

I

<system.webServer>
  <httpErrors errorMode="Detailed" existingResponse="PassThrough"></httpErrors>
</system.webServer>
Rick Glos
źródło
11

Miałem podobny problem podczas wysyłania do punktu końcowego WebAPI. Wyłączając CustomErrors = Off, mogłem zobaczyć rzeczywisty błąd, który jest jednym z brakujących bibliotek dll.

ctong
źródło
10

Na wypadek, gdyby to komuś pomogło:

Miałem podobny problem i zgodnie z instrukcjami Natesa dodałem:

<system.web>
     <customErrors mode="Off"/>
 </system.web>

To pokazało mi więcej informacji o błędzie:

"ExceptionMessage": "Nie można załadować określonego zasobu metadanych.", "ExceptionType": "System.Data.Entity.Core.MetadataException", "StackTrace": "at System.Data.Entity.Core.Metadata.Edm.MetadataArtifactLoaderCompositeResource .LoadResources (...

Wtedy przypomniałem sobie, że przeniosłem plik edmx do innej lokalizacji i zapomniałem zmienić węzeł connectionstrings w konfiguracji (węzeł connectionstrings został umieszczony w osobnym pliku przy użyciu „configSource”, ale to już inna historia).

hormberg
źródło
Zdarzyło mi się to podczas dodawania OData i AutoMapper do internetowego interfejsu API w asp.net - mam nadzieję, że te słowa kluczowe pomogą komuś dotrzeć do tego posta, a metoda try / catch nie zadziałała w moim przypadku, więc musiałem zobaczyć surowy wynik
Ekus
0

Mój plik Swagger XML nie został wdrożony w \ bin:

GlobalConfiguration.Configuration
  .EnableSwagger(c =>
  {
    c.SingleApiVersion("v1", "SwaggerDemoApi");
    c.IncludeXmlComments(string.Format(@"{0}\bin\SwaggerDemoApi.XML", 
                         System.AppDomain.CurrentDomain.BaseDirectory));
    c.DescribeAllEnumsAsStrings();
  })

http://wmpratt.com/swagger-and-asp-net-web-api-part-1/

wprowadź opis obrazu tutaj

Musiało być ustawione w konfiguracji wydania, a także w konfiguracji debugowania.

RaSor
źródło
0

Jeśli masz <deployment retail="true"/>plik machine.config w programie .NET Framework, nie zobaczysz szczegółowych komunikatów o błędach. Upewnij się, że ustawienie jest fałszywe lub nie istnieje.

Eric H.
źródło
0

Więc bezskutecznie wypróbowałem wszystkie sugerowane rozwiązania. Wszystko, co zrobiłem, to ustawić uruchamianie aplikacji z serwera i wyświetlał błąd w całości. Powinno to zadziałać, gdy ustawiłem tryb customErrors na false, ale tak się nie stało. W momencie, gdy przeglądałem API z serwera, mogłem zobaczyć problem.

Książę Tegaton
źródło