This topic describes how to use the XPO Profiler to profile ASP.NET Core applications.
Connection Setup
Create the following controller:
using DevExpress.Xpo.Logger;
using DevExpress.Xpo.Logger.Transport;
using Microsoft.AspNetCore.Mvc;
// ...
[ApiController]
[Route("[controller]/[action]")]
public class XpoLoggerController : ControllerBase {
readonly ILogSource logger;
public XpoLoggerController(ILogSource logger) {
this.logger = logger;
}
[HttpGet]
public LogMessage[] GetCompleteLog() {
return logger.GetCompleteLog();
}
[HttpGet]
public LogMessage GetMessage() {
return logger.GetMessage();
}
[HttpGet]
public LogMessage[] GetMessages(int messagesAmount) {
return logger.GetMessages(messagesAmount);
}
}
Imports DevExpress.Xpo.Logger
Imports DevExpress.Xpo.Logger.Transport
Imports Microsoft.AspNetCore.Mvc
' ...
<ApiController, Route("[controller]/[action]")> _
Public Class XpoLoggerController
Inherits ControllerBase
Private ReadOnly logger As ILogSource
Public Sub New(ByVal logger As ILogSource)
Me.logger = logger
End Sub
<HttpGet> _
Public Function GetCompleteLog() As LogMessage()
Return logger.GetCompleteLog()
End Function
<HttpGet> _
Public Function GetMessage() As LogMessage
Return logger.GetMessage()
End Function
<HttpGet> _
Public Function GetMessages(ByVal messagesAmount As Integer) As LogMessage()
Return logger.GetMessages(messagesAmount)
End Function
End Class
Add the following code to the Startup.ConfigureServices method:
DevExpress.Xpo.Logger.ILogger logger = new DevExpress.Xpo.Logger.LoggerBase(5000);
DevExpress.Xpo.Logger.LogManager.SetTransport(logger);
services.AddSingleton((DevExpress.Xpo.Logger.Transport.ILogSource)logger);
Dim logger As DevExpress.Xpo.Logger.ILogger = New DevExpress.Xpo.Logger.LoggerBase(5000)
DevExpress.Xpo.Logger.LogManager.SetTransport(logger)
services.AddSingleton(CType(logger, DevExpress.Xpo.Logger.Transport.ILogSource))
Make sure that the Configure method has the code that adds endpoints for controller actions:
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
// ...
app.UseEndpoints(endpoints => {
// ...
endpoints.MapControllers();
});
}
' This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Public Sub Configure(ByVal app As IApplicationBuilder, ByVal env As IWebHostEnvironment)
' ...
app.UseEndpoints(Function(endpoints) ConfigureEndpoints(endpoints))
End Sub
Private Function ConfigureEndpoints(ByVal endpoints As Object) As Boolean
endpoints.MapControllers()
Return True
End Function
Run the XPO Profiler. Click File | New. In the New Host dialog, supply the following parameters:
| Parameter |
Value |
| Binding type |
Select “WebApi” in the drop-down list. |
| Server name |
Specify the hostname. The default protocol is HTTP. To use HTTPS, add the protocol prefix to the hostname (for example, “https://myserver”). |
| Port |
Specify the web site’s port number. |
| Path |
Specify the path to the controller (demonstrated in the first step) that corresponds to the web application (for example, “XpoLogger”). |

Click Test to test the connection.
Authentication Setup
XPO Profiler supports the following authentication types when using WebAPI binding:
| Authentication Type |
Description |
Authentication Dialog |
| Anonymous |
Your web application should provide anonymous access to the controller demonstrated in the Connection Setup section. |
None |
| Basic |
XPO profiler displays the Authentication dialog where you can specify the login and password. |
 |
| Token-Based |
XPO profiler displays the Authentication dialog where you can specify the authentication token. Your web application should implement a custom authentication handler (see the section below for details). |
 |
Token-Based Authentication
Implement the following XpoProfilerTokenHandler authentication handler:
using Microsoft.AspNetCore.Authentication;
// ...
class XpoProfilerTokenHandler : AuthenticationHandler<AuthenticationSchemeOptions>, IAuthenticationHandler {
const string ValidToken = "xpoxpo";
public const string AuthScheme = "XpoProfilerToken";
public XpoProfilerTokenHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { }
protected override Task<AuthenticateResult> HandleAuthenticateAsync() {
return Task.Run(() => {
string header = Context.Request.Headers["Authorization"].FirstOrDefault(h => h.StartsWith(AuthScheme));
if(header != null) {
string token = header.Substring(AuthScheme.Length + 1);
if(token == ValidToken) {
var principal = new ClaimsPrincipal(new ClaimsIdentity(null, AuthScheme));
return AuthenticateResult.Success(new AuthenticationTicket(principal, AuthScheme));
}
}
return AuthenticateResult.NoResult();
});
}
}
Imports Microsoft.AspNetCore.Authentication
' ...
Friend Class XpoProfilerTokenHandler
Inherits AuthenticationHandler(Of AuthenticationSchemeOptions)
Implements IAuthenticationHandler
Private Const ValidToken As String = "xpoxpo"
Public Const AuthScheme As String = "XpoProfilerToken"
Public Sub New(ByVal options As IOptionsMonitor(Of AuthenticationSchemeOptions), ByVal logger As ILoggerFactory, _
ByVal encoder As UrlEncoder, ByVal clock As ISystemClock)
MyBase.New(options, logger, encoder, clock)
End Sub
Protected Overrides Function HandleAuthenticateAsync() As Task(Of AuthenticateResult)
Return Task.Run(Function()
Dim header As String = Context.Request.Headers("Authorization").FirstOrDefault(Function(h) h.StartsWith(AuthScheme))
If header IsNot Nothing Then
Dim token As String = header.Substring(AuthScheme.Length + 1)
If token = ValidToken Then
Dim principal As New ClaimsPrincipal(New ClaimsIdentity(Nothing, AuthScheme))
Return AuthenticateResult.Success(New AuthenticationTicket(principal, AuthScheme))
End If
End If
Return AuthenticateResult.NoResult()
End Function)
End Function
End Class
Important
The XpoProfilerTokenHandler.ValidToken constant value (“xpoxpo“ in this example) is a token that you should specify in the XPO Profiler’s Authentication dialog to connect to your web application. Replace “xpoxpo“ with a custom secret token string for security purposes.
Register your custom authentication handler in the Startup.ConfigureServices method declared in the Startup.cs file.
public void ConfigureServices(IServiceCollection services) {
services
.AddAuthentication( /*your default authentication_scheme*/)
.AddScheme<AuthenticationSchemeOptions, XpoProfilerTokenHandler>(XpoProfilerTokenHandler.AuthScheme, null);
}
Public Sub ConfigureServices(ByVal services As IServiceCollection)
services.AddAuthentication() _ ' your default authentication_scheme
.AddScheme(Of AuthenticationSchemeOptions, XpoProfilerTokenHandler)(XpoProfilerTokenHandler.AuthScheme, Nothing)
End Sub
Apply the Authorize attribute to your XpoLoggerController class (demonstrated in the Connection Setup section).
using Microsoft.AspNetCore.Authorization;
// ...
[Authorize(AuthenticationSchemes = XpoProfilerTokenHandler.AuthScheme)]
public class XpoLoggerController : Controller {
// ...
}
Imports Microsoft.AspNetCore.Authorization
' ...
<Authorize(AuthenticationSchemes := XpoProfilerTokenHandler.AuthScheme)>
Public Class XpoLoggerController
Inherits Controller
' ...
End Class
See Also