Capturer des requêtes SOAP à un ASP.NET service Web ASMX
tenir compte de la nécessité d'enregistrer les requêtes SOAP entrantes à un ASP.NET service Web ASMX. La tâche consiste à saisir le XML brut envoyé au service web.
Le message entrant doit être enregistré pour déboguer l'inspection. L'application a déjà sa propre bibliothèque de journalisation en cours d'utilisation, donc l'idéal d'utilisation serait quelque chose comme ceci:
//string or XML, it doesn't matter.
string incomingSoapRequest = GetSoapRequest();
Logger.LogMessage(incomingSoapRequest);
- Existe-t-il des solutions simples pour capturer le XML brut des requêtes SOAP entrantes?
- quel quels événements traiteriez-vous pour avoir accès à cet objet et aux propriétés pertinentes?
- y a-t-il un moyen pour L'IIS de capturer la requête entrante et de la pousser vers un log?
5 réponses
Un moyen de capturer le message brut est d'utiliser SoapExtensions.
une alternative à SoapExtensions est d'implémenter IHttpModule et de saisir le flux d'entrée au fur et à mesure qu'il arrive.
public class LogModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += this.OnBegin;
}
private void OnBegin(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpContext context = app.Context;
byte[] buffer = new byte[context.Request.InputStream.Length];
context.Request.InputStream.Read(buffer, 0, buffer.Length);
context.Request.InputStream.Position = 0;
string soapMessage = Encoding.ASCII.GetString(buffer);
// Do something with soapMessage
}
public void Dispose()
{
throw new NotImplementedException();
}
}
vous pouvez également implémenter en plaçant le code dans Global.asax.cs
protected void Application_BeginRequest(object sender, EventArgs e)
{
// Create byte array to hold request bytes
byte[] inputStream = new byte[HttpContext.Current.Request.ContentLength];
// Read entire request inputstream
HttpContext.Current.Request.InputStream.Read(inputStream, 0, inputStream.Length);
//Set stream back to beginning
HttpContext.Current.Request.InputStream.Position = 0;
//Get XML request
string requestString = ASCIIEncoding.ASCII.GetString(inputStream);
}
j'ai une méthode utilitaire dans mon service web que j'utilise pour capturer la requête quand quelque chose se produit que je ne m'attends pas comme une exception non manipulée.
/// <summary>
/// Captures raw XML request and writes to FailedSubmission folder.
/// </summary>
internal static void CaptureRequest()
{
const string procName = "CaptureRequest";
try
{
log.WarnFormat("{0} - Writing XML request to FailedSubmission folder", procName);
byte[] inputStream = new byte[HttpContext.Current.Request.ContentLength];
//Get current stream position so we can set it back to that after logging
Int64 currentStreamPosition = HttpContext.Current.Request.InputStream.Position;
HttpContext.Current.Request.InputStream.Position = 0;
HttpContext.Current.Request.InputStream.Read(inputStream, 0, HttpContext.Current.Request.ContentLength);
//Set back stream position to original position
HttpContext.Current.Request.InputStream.Position = currentStreamPosition;
string xml = ASCIIEncoding.ASCII.GetString(inputStream);
string fileName = Guid.NewGuid().ToString() + ".xml";
log.WarnFormat("{0} - Request being written to filename: {1}", procName, fileName);
File.WriteAllText(Configuration.FailedSubmissionsFolder + fileName, xml);
}
catch
{
}
}
puis sur le web.config je stocke plusieurs valeurs D'application qui définissent le niveau que je veux utiliser pour capturer la requête.
<!-- true/false - If true will write to an XML file the raw request when any Unhandled exception occurrs -->
<add key="CaptureRequestOnUnhandledException" value="true"/>
<!-- true/false - If true will write to an XML file the raw request when any type of error is returned to the client-->
<add key="CaptureRequestOnAllFailures" value="false"/>
<!-- true/false - If true will write to an XML file the raw request for every request to the web service -->
<add key="CaptureAllRequests" value="false"/>
puis dans ma Application_BeginRequest Je l'ai modifié comme ça. Notez que La Configuration est une classe statique que je crée pour lire les propriétés de web.config et d'autres domaines.
protected void Application_BeginRequest(object sender, EventArgs e)
{
if(Configuration.CaptureAllRequests)
{
Utility.CaptureRequest();
}
}
Vous savez que vous n'avez pas en fait, besoin de créer un HttpModule
droit?
vous pouvez aussi lire le contenu du Request.InputStream
à partir de votre asmx WebMethod
.
Ici un article que j'ai écrit sur cette approche.
le Code est comme suit:
using System;
using System.Collections.Generic;
using System.Web;
using System.Xml;
using System.IO;
using System.Text;
using System.Web.Services;
using System.Web.Services.Protocols;
namespace SoapRequestEcho
{
[WebService(
Namespace = "http://soap.request.echo.com/",
Name = "SoapRequestEcho")]
public class EchoWebService : WebService
{
[WebMethod(Description = "Echo Soap Request")]
public XmlDocument EchoSoapRequest(int input)
{
// Initialize soap request XML
XmlDocument xmlSoapRequest = new XmlDocument();
// Get raw request body
Stream receiveStream = HttpContext.Current.Request.InputStream;
// Move to beginning of input stream and read
receiveStream.Position = 0;
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
// Load into XML document
xmlSoapRequest.Load(readStream);
}
// Return
return xmlSoapRequest;
}
}
}
Il n'est pas facile à faire. Vous aurez à mettre en œuvre un SoapExtension. L'exemple du lien précédent montre une extension qui peut être utilisée pour enregistrer les données.
si vous utilisez WCF, vous pouvez simplement configurer la configuration pour produire des journaux de messages.
Selon Steven de Salas, vous pouvez utiliser le Request.InputStream
propriété dans la méthode Web. Je n'ai pas essayé cela, mais il dit qu'il travaille.
je voudrais tester cela avec http et https, et avec et sans autres extensions SOAP en cours d'exécution en même temps. Ce sont des choses qui pourraient affecter quel genre de flux le InputStream
est réglé. Certains flux ne peuvent pas chercher, par exemple, ce qui pourrait vous laisser avec un flux positionné après la fin des données, et que vous ne pouvez pas déplacer au début.
je sais que j'ai 4 ans de retard... mais maintenant, nous avons un violon pour faire de même.