Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
370 views
in Technique[技术] by (71.8m points)

asp.net - How to trace ScriptService WebService requests?

I have a SoapExtension that is intended to log all SOAP requests and responses. It works just fine for calls from an application using the MS Soap Toolkit (OnBase Workflow). But it doesn't work for calls made by $.ajax() on an html page. Here's an example:

$.ajax({
    type: "POST",
    url: url,
    data: data,
    contentType: "application/json; charset=utf-8",
    dataType: "json"
});

It's calling an ASP.NET 3.5 WebService marked with WebService and ScriptService attributes:

[WebService(Namespace = XmlSerializationService.DefaultNamespace)]
[ScriptService]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class DepartmentAssigneeService : WebService
{
    private readonly DepartmentAssigneeController _controller = new DepartmentAssigneeController();

    /// <summary>
    /// Fetches the role items.
    /// </summary>
    /// <returns></returns>
    [WebMethod]
    [SoapLog]
    public ListItem[] FetchDepartmentItems()
    {
        return CreateListItems(_controller.FetchDepartments());
    }
}

And here are the basics for the SoapExtension and SoapExtensionAttribute:

public class LoggingSoapExtension : SoapExtension, IDisposable { /*...*/ }

[AttributeUsage(AttributeTargets.Method)]
public sealed class SoapLogAttribute : SoapExtensionAttribute { /*...*/ }

Am I missing something that would allow LoggingSoapExtension to execute on $.ajax() requests?

Update

@Chris Brandsma

It might be because you are requesting Json results instead of XML via your web service (dataType: "json"). So the ScriptService attribute is being activated, but you are not sending SOAP messages.

That answers why the SoapExtension isn't working. Any suggestions for tracing with ScriptService? The only thing that comes to mind is a ScriptService base class that provides a method to log a request. But then I'd have to call that method in every WebMethod in every ScriptService WebService (I have quite a few). I'd like to use something as clean and simple as a SoapExtension attribute, if possible.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I found a solution. By using an IHttpModule I can log requests from anything (SOAP, JSON, forms, etc). In the implementation below, I've chosen to log all .asmx and .ashx requests. This replaces LoggingSoapExtension from the question.

public class ServiceLogModule : IHttpModule
{
    private HttpApplication _application;
    private bool _isWebService;
    private int _requestId;
    private string _actionUrl;

    #region IHttpModule Members

    public void Dispose()
    {
    }

    public void Init(HttpApplication context)
    {
        _application = context;
        _application.BeginRequest += ContextBeginRequest;
        _application.PreRequestHandlerExecute += ContextPreRequestHandlerExecute;
        _application.PreSendRequestContent += ContextPreSendRequestContent;
    }

    #endregion

    private void ContextPreRequestHandlerExecute(object sender, EventArgs e)
    {
        _application.Response.Filter = new CapturedStream(_application.Response.Filter,
                                                          _application.Response.ContentEncoding);
    }

    private void ContextBeginRequest(object sender, EventArgs e)
    {
        string ext = VirtualPathUtility.GetExtension(_application.Request.FilePath).ToLower();
        _isWebService = ext == ".asmx" || ext == ".ashx";

        if (_isWebService)
        {
            ITraceLog traceLog = TraceLogFactory.Create();
            _actionUrl = _application.Request.Url.PathAndQuery;

            StreamReader reader = new StreamReader(_application.Request.InputStream);
            string message = reader.ReadToEnd();
            _application.Request.InputStream.Position = 0;

            _requestId = traceLog.LogRequest(_actionUrl, message);
        }
    }

    private void ContextPreSendRequestContent(object sender, EventArgs e)
    {
        if (_isWebService)
        {
            CapturedStream stream = _application.Response.Filter as CapturedStream;
            if (stream != null)
            {
                ITraceLog traceLog = TraceLogFactory.Create();
                traceLog.LogResponse(_actionUrl, stream.StreamContent, _requestId);
            }
        }
    }
}

I borrowed heavily from Capturing HTML generated from ASP.NET.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...