Logo

Before to start

You can find a complete sample at this address: OrbintSoft.Yauaa.WebSample.AspNetCore

In this example we will use an ASP.NET Core 3.0 MVC project.
I will not explain how to create and configure an ASP.NET Core project, in this guide I'll just focus on how to use Yauaa on real case application.

Create a user agent model.

First we create an interface for our model with the fields that we need.
This allows us to abstract our model for IOC.

public interface IUserAgentModel
{
    string AgentClass { get; set; }
    string AgentName { get; set; }
    Version AgentVersion { get; set; }
    string DeviceBrand { get; set; }
    string DeviceClass { get; set; }
    string DeviceCpu { get; set; }
    string DeviceCpuBits { get; set; }
    string DeviceName { get; set; }
    string LayoutEngineClass { get; set; }
    string LayoutEngineName { get; set; }
    Version LayoutEngineVersion { get; set; }
    string OperatingSystemClass { get; set; }
    string OperatingSystemName { get; set; }
    Version OperatingSystemVersion { get; set; }
    string UserAgentString { get; }
}

Then we can create the concrete class.
Not that we also add the user agent string as readonly property.

public class UserAgentModel : IUserAgentModel
{
    public string UserAgentString { get; }
    public string AgentClass { get; set; }
    public string AgentName { get; set; }
    public Version AgentVersion { get; set; }
    public string DeviceBrand { get; set; }
    public string DeviceClass { get; set; }
    public string DeviceName { get; set; }
    public string LayoutEngineClass { get; set; }
    public string LayoutEngineName { get; set; }
    public Version LayoutEngineVersion { get; set; }
    public string OperatingSystemClass { get; set; }
    public string OperatingSystemName { get; set; }
    public Version OperatingSystemVersion { get; set; }
    public string DeviceCpu { get; set; }
    public string DeviceCpuBits { get; set; }

    public UserAgentModel(string useragentString)
    {
        UserAgentString = useragentString;
    }
}

Create the mapper.

We create an interface that will be used with dependency injections.

public interface IUserAgentMapper
{
    IUserAgentModel Enrich(string userAgent); //fills the useragent model
    string GetUserAgentString(IUserAgentModel record); //Gets the useragent string       
}

We implement it using the user agent annotation mapper.
Every attribute will be automatically mapped thanks to YauaaField attribute.
We implement also a custom conversion for version fields.
Pay attention this is just an example, conversion is not perfect, in case of semantic versioning or other string versioning system, they cannot be converted.

public class UserAgentMapper : IUserAgentAnnotationMapper<IUserAgentModel>, IUserAgentMapper
{
    private readonly UserAgentAnnotationAnalyzer<IUserAgentModel> userAgentAnalyzer;

    public UserAgentMapper()
    {
        userAgentAnalyzer = new UserAgentAnnotationAnalyzer<IUserAgentModel>();
        userAgentAnalyzer.Initialize(this);
    }

    [YauaaField(DefaultUserAgentFields.AGENT_CLASS)]
    public void SetAgentClass(UserAgentModel record, string value)
    {
        record.AgentClass = value;
    }

    [YauaaField(DefaultUserAgentFields.AGENT_NAME)]
    public void SetAgentName(UserAgentModel record, string value)
    {
        record.AgentName = value;
    }

    [YauaaField(DefaultUserAgentFields.AGENT_VERSION)]
    public void SetAgentVersion(UserAgentModel record, string value)
    {
        Version.TryParse(value, out var version);
        record.AgentVersion = version;
    }

    [YauaaField(DefaultUserAgentFields.DEVICE_BRAND)]
    public void SetDeviceBrand(UserAgentModel record, string value)
    {
        record.DeviceBrand = value;
    }

    [YauaaField(DefaultUserAgentFields.DEVICE_CLASS)]
    public void SetDeviceClass(UserAgentModel record, string value)
    {
        record.DeviceClass = value;
    }

    [YauaaField(DefaultUserAgentFields.DEVICE_NAME)]
    public void SetDeviceName(UserAgentModel record, string value)
    {
        record.DeviceName = value;
    }

    [YauaaField(DefaultUserAgentFields.LAYOUT_ENGINE_CLASS)]
    public void SetLayoutEngineClass(UserAgentModel record, string value)
    {
        record.LayoutEngineClass = value;
    }

    [YauaaField(DefaultUserAgentFields.LAYOUT_ENGINE_NAME)]
    public void SetLayoutEngineName(UserAgentModel record, string value)
    {
        record.LayoutEngineName = value;
    }

    [YauaaField(DefaultUserAgentFields.LAYOUT_ENGINE_VERSION)]
    public void SetLayoutEngineVersion(UserAgentModel record, string value)
    {
        Version.TryParse(value, out var version);
        record.LayoutEngineVersion = version;
    }

    [YauaaField(DefaultUserAgentFields.OPERATING_SYSTEM_CLASS)]
    public void SetOperatingSystemClass(UserAgentModel record, string value)
    {
        record.OperatingSystemClass = value;
    }

    [YauaaField(DefaultUserAgentFields.OPERATING_SYSTEM_NAME)]
    public void SetOperatingSystemName(UserAgentModel record, string value)
    {
        record.OperatingSystemName = value;
    }

    [YauaaField(DefaultUserAgentFields.OPERATING_SYSTEM_VERSION)]
    public void SetOperatingSystemVersion(UserAgentModel record, string value)
    {
        Version.TryParse(value, out var version);
        record.OperatingSystemVersion = version;
    }

    [YauaaField(DefaultUserAgentFields.DEVICE_CPU)]
    public void SetDeviceCpu(UserAgentModel record, string value)
    {
        record.DeviceCpu = value;
    }

    [YauaaField(DefaultUserAgentFields.DEVICE_CPU_BITS)]
    public void SetDeviceCpuBits(UserAgentModel record, string value)
    {
        record.DeviceCpuBits = value;
    }

    public IUserAgentModel Enrich(string userAgent)
    {
        var model = new UserAgentModel(userAgent);
        return userAgentAnalyzer.Map(model);
    }

    public string GetUserAgentString(IUserAgentModel record)
    {
        return record.UserAgentString;
    }
}

Create the service.

We create the interface of our service that will be used for dependency injection.

public interface IUserAgentService
{
    IUserAgentModel Parse(string userAgentString);
}

Then we implement provide a very simple implementation with the injection of the IUserAgentMapper.

public class UserAgentService : IUserAgentService
{
    private readonly IUserAgentMapper userAgentMapper;
    public UserAgentService(IUserAgentMapper userAgentMapper)
    {
        this.userAgentMapper = userAgentMapper;
    }

    public IUserAgentModel Parse(string userAgentString)
    {
        return userAgentMapper.Enrich(userAgentString);
    }
}

Dependency injection.

We create an extension method to register our components.

public static IServiceCollection AddUserAgentService(this IServiceCollection serviceCollection)
{
    return serviceCollection
        .AddSingleton<IUserAgentMapper, UserAgentMapper>()
        .AddSingleton<IUserAgentService, UserAgentService>();
}

And we register it in startup ConfigureServices.

services.AddUserAgentService();

Create a web API.

We can create a new controller to parse our user agent.

[ApiController]
[Route("[Controller]")]
public class ApiController : ControllerBase
{
    private readonly IUserAgentService userAgentService;

    public ApiController(IUserAgentService userAgentService)
    {
        this.userAgentService = userAgentService;
    }

    [HttpGet]
    public IUserAgentModel Get()
    {
        string userAgent = this.HttpContext?.Request?.Headers?.FirstOrDefault(s => s.Key.ToLower() == "user-agent").Value;
        return userAgentService.Parse(userAgent);
    }

    [HttpPost]
    public IUserAgentModel Post(string userAgent)
    {            
        return userAgentService.Parse(userAgent);
    }
}