web-dev-qa-db-fra.com

ASP.NET Web Api HttpResponseException 400 (requête incorrecte) piraté par IIS

J'écris un service Web API et j'essaie de renvoyer une (400) requête incorrecte si mon ModelState n'est pas valide. Je ne veux pas qu'un corps de réponse soit attaché à cela. Il semble que IIS détourne ma réponse et renvoie toujours un type de contenu text/html avec une longue page d'erreur stylée. C'est un problème.

    [HttpPost]
    public void Link(LinkDeviceModel model)
    {

        if (ModelState.IsValid)
        {
            try
            {
                model.Save();
            }
            catch (Exception ex)
            {
                ErrorSignal.FromCurrentContext().Raise(ex);
                throw new HttpResponseException(ex.Message, HttpStatusCode.InternalServerError);
            }
        }
        else
        {
            throw new HttpResponseException(HttpStatusCode.BadRequest);
        }
    }

Voici ma demande de violoneux:

POST http://localhost/myapp/service/link HTTP/1.1
Host: localhost
Content-Length: 112
Content-Type: application/json
Accept: application/json

{"DeviceUniqueId":"CC9C6FC0-7D06-11E1-8B0E-31564824019B", "UserName": "[email protected]"," Pin": "111111"}

Et ma réponse erronée, pleine de corps, réponse:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<title>IIS 7.5 Detailed Error - 400.0 - Bad Request</title> 
<style type="text/css"> 
<!-- 
body{margin:0;font-size:.7em;font-family:Verdana,Arial,Helvetica,sans-serif;background:#CBE1EF;} 
code{margin:0;color:#006600;font-size:1.1em;font-weight:bold;} 
.config_source code{font-size:.8em;color:#000000;} 
pre{margin:0;font-size:1.4em;Word-wrap:break-Word;} 
ul,ol{margin:10px 0 10px 40px;} 
ul.first,ol.first{margin-top:5px;} 
fieldset{padding:0 15px 10px 15px;} 
.summary-container fieldset{padding-bottom:5px;margin-top:4px;} 
legend.no-expand-all{padding:2px 15px 4px 10px;margin:0 0 0 -12px;} 
legend{color:#333333;padding:4px 15px 4px 10px;margin:4px 0 8px -12px;_margin-top:0px; 
 border-top:1px solid #EDEDED;border-left:1px solid #EDEDED;border-right:1px solid #969696; 
 border-bottom:1px solid #969696;background:#E7ECF0;font-weight:bold;font-size:1em;} 
a:link,a:visited{color:#007EFF;font-weight:bold;} 
a:hover{text-decoration:none;} 
h1{font-size:2.4em;margin:0;color:#FFF;} 
h2{font-size:1.7em;margin:0;color:#CC0000;} 
h3{font-size:1.4em;margin:10px 0 0 0;color:#CC0000;} 
h4{font-size:1.2em;margin:10px 0 5px 0; 
}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS",Verdana,sans-serif; 
 color:#FFF;background-color:#5C87B2; 
}#content{margin:0 0 0 2%;position:relative;} 
.summary-container,.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;} 
.config_source{background:#fff5c4;} 
.content-container p{margin:0 0 10px 0; 
}#details-left{width:35%;float:left;margin-right:2%; 
}#details-right{width:63%;float:left;overflow:hidden; 
}#server_version{width:96%;_height:1px;min-height:1px;margin:0 0 5px 0;padding:11px 2% 8px 2%;color:#FFFFFF; 
 background-color:#5A7FA5;border-bottom:1px solid #C1CFDD;border-top:1px solid #4A6C8E;font-weight:normal; 
 font-size:1em;color:#FFF;text-align:right; 
}#server_version p{margin:5px 0;} 
table{margin:4px 0 4px 0;width:100%;border:none;} 
td,th{vertical-align:top;padding:3px 0;text-align:left;font-weight:bold;border:none;} 
th{width:30%;text-align:right;padding-right:2%;font-weight:normal;} 
thead th{background-color:#ebebeb;width:25%; 
}#details-right th{width:20%;} 
table tr.alt td,table tr.alt th{background-color:#ebebeb;} 
.highlight-code{color:#CC0000;font-weight:bold;font-style:italic;} 
.clear{clear:both;} 
.preferred{padding:0 5px 2px 5px;font-weight:normal;background:#006633;color:#FFF;font-size:.8em;} 
--> 
</style> 

</head> 
<body> 
<div id="header"><h1>Server Error in Application "DEFAULT WEB SITE/MYAPP"</h1></div> 
<div id="server_version"><p>Internet Information Services 7.5</p></div> 
<div id="content"> 
<div class="content-container"> 
 <fieldset><legend>Error Summary</legend> 
  <h2>HTTP Error 400.0 - Bad Request</h2> 
  <h3>Bad Request</h3> 
 </fieldset> 
</div> 
<div class="content-container"> 
 <fieldset><legend>Detailed Error Information</legend> 
  <div id="details-left"> 
   <table border="0" cellpadding="0" cellspacing="0"> 
    <tr class="alt"><th>Module</th><td>ManagedPipelineHandler</td></tr> 
    <tr><th>Notification</th><td>ExecuteRequestHandler</td></tr> 
    <tr class="alt"><th>Handler</th><td>System.Web.Http.WebHost.HttpControllerHandler</td></tr> 
    <tr><th>Error Code</th><td>0x00000000</td></tr> 

   </table> 
  </div> 
  <div id="details-right"> 
   <table border="0" cellpadding="0" cellspacing="0"> 
    <tr class="alt"><th>Requested URL</th><td>http://localhost:80/myapp/service/link</td></tr> 
    <tr><th>Physical Path</th><td>C:\workspace\myapp\service\link</td></tr> 
    <tr class="alt"><th>Logon Method</th><td>Anonymous</td></tr> 
    <tr><th>Logon User</th><td>Anonymous</td></tr> 

   </table> 
   <div class="clear"></div> 
  </div> 
 </fieldset> 
</div> 
<div class="content-container"> 
 <fieldset><legend>Most likely causes:</legend> 
  <ul>  <li></li> </ul> 
 </fieldset> 
</div> 
<div class="content-container"> 
 <fieldset><legend>Things you can try:</legend> 
  <ul>  <li>Create a tracing rule to track failed requests for this HTTP status code. For more information about creating a tracing rule for failed requests, click <a href="http://go.Microsoft.com/fwlink/?LinkID=66439">here</a>. </li> </ul> 
 </fieldset> 
</div> 


<div class="content-container"> 
 <fieldset><legend>Links and More Information</legend> 
  The request could not be understood by the server due to malformed syntax. 
  <p><a href="http://go.Microsoft.com/fwlink/?LinkID=62293&amp;IIS70Error=400,0,0x00000000,7601">View more information &raquo;</a></p> 
  <p>Microsoft Knowledge Base Articles:</p> 
 <ul><li></li></ul> 

 </fieldset> 
</div> 
</div> 
</body> 
</html> 

J'ai essayé de définir TrySkipIisCustomErrors = True avec beaucoup d'espoir, mais sans succès. Des idées? Apprécié. Merci.

16
kmehta

Essayez d'ajouter ceci à votre web.config. J'ai eu un problème très similaire que cela a résolu.

<configuration>
  <system.webServer>
    <httpErrors existingResponse="PassThrough" />
  </system.webServer>
</configuration>
29
Antony Scott

Dans de tels cas, il suffit généralement de définir TrySkipIisCustomErrors = true sur l'objet de réponse, mais dans le cas d'une API Web, cela ne suffit parfois pas (l'API Web tente même de définir cet indicateur en interne par lui-même). Pour de telles situations, vous pouvez envisager de modifier la configuration IIS. S'il vous plaît jetez un oeil ici (vous devriez être principalement intéressé par existingResponse = "PassThrough").

4
tpeczek

En supposant que vous êtes à l'intérieur de votre APIController et que vous n'avez pas besoin d'un ExceptionFilterAttribute pour effectuer un travail supplémentaire pour la réponse, renvoyez simplement une réponse avec le code d'état d'erreur au lieu de générer une exception HttpResponseException.

return Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid model.");
2
Mark Seefeldt

J'étais dans une situation où j'appelais un point de terminaison WebApi depuis un autre, et après avoir lu que les clients HTTP devaient être statiques, j'ai apporté cette modification. Fonctionnait correctement pour quelques dizaines de messages, mais était ensuite intercepté par l’instance d’auto-hôte, ce qui renverrait une demande de 400 requêtes incorrectes. Il ne semblait y avoir aucun problème, en particulier avec le succès initial, mais mon code d'origine ajoutait un en-tête par défaut au client avant l'appel. Une fois le client statique, cela aurait signifié que j’avais ajouté l’en-tête plusieurs fois au même client. J'ai changé le code pour envoyer, créer et envoyer un HttpRequestMessage au lieu de laisser le client le faire, et j'ai ajouté l'en-tête à la demande. Semble avoir résolu mon problème.

0
William T. Mallard

Je frappais dans le même état en revenant:

httpResponseMessage = context.Request.CreateResponse(statusCode);

L'ajout de <httpErrors existingResponse = "PassThrough"> n'a pas résolu le problème, le type de contenu et le corps du contenu étaient manquants dans la réponse.

Ce qui a résolu le problème était de construire le HttpResponseMessage comme ceci:

var httpResponseMessage = context.Request.CreateResponse(statusCode, reasonPhrase);

En incluant le paramètre 'value' (dans ce cas, 'reasonPhrase'), le type de contenu et le corps du contenu étaient présents dans la réponse.

0
Beans

J'ai eu le même problème avec l'application Asp.Net Webform. Le client envoie un appel ajax au gestionnaire Web du serveur (* .ashx).

Je voulais renvoyer le message d'exception à l'utilisateur. Le gestionnaire Web renvoie uniquement le message d'exception et le code de statut http 400.

L'astuce est dans Response.TrySkipIisCustomErrors = true;

try
{
//do some coding
}
catch (Exception exception)
{
    Log.Error(exception);
    context.Server.ClearError();
    context.Response.TrySkipIisCustomErrors = true;
    context.Response.ContentType = "text/plain";
    context.Response.Write(exception.Message);
    context.Response.StatusCode = 400;
    //400 Bad Request
    //The server cannot or will not process the request due to an apparent client error
    //
    //intentionally hidden exception 
    //prevent to send yellow page of death in ajax response
}
0
Vojta