\r\n

51Degrees Device Detection .NET  4.2

Device detection services for 51Degrees Pipeline

AspNetCore2.1/Startup.cs

This example shows how to integrate the Pipeline API with a device detection engine into an ASP.NET Core web app.The source code for this example is available in full on GitHub.

This example can be configured to use the 51Degrees cloud service or a local data file. If you don't already have data file you can obtain one from the device-detection-data GitHub repository.

To use the cloud service you will need to create a resource key. The resource key is used as short-hand to store the particular set of properties you are interested in as well as any associated license keys that entitle you to increased request limits and/or paid-for properties.

You can create a resource key using the 51Degrees Configurator.

Required NuGet Dependencies:

  1. Add Pipeline configuration options to appsettings.json. (or a separate file if you prefer. Just don't forget to add that file to your startup.cs) Example on-premise configuration:
    {
    "PipelineOptions": {
    "Elements": [
    {
    "BuilderName": "DeviceDetectionHashEngineBuilder",
    "BuildParameters": {
    "DataFile": "51Degrees-LiteV4.1.hash",
    "CreateTempDataCopy": false,
    "AutoUpdate": false,
    "PerformanceProfile": "LowMemory",
    "DataFileSystemWatcher": false,
    "DataUpdateOnStartUp": false
    }
    }
    ]
    }
    }

Example cloud configuration:

{
"PipelineOptions": {
"Elements": [
{
"BuilderName": "CloudRequestEngineBuilder",
"BuildParameters": {
"ResourceKey": "YourKey"
}
},
{
"BuilderName": "DeviceDetectionCloudEngineBuilder"
}
]
}
}
  1. Add builders and the Pipeline to the server's services.
    public class Startup
    {
    ...
    public void ConfigureServices(IServiceCollection services)
    {
    ...
    services.AddSingleton<DeviceDetectionHashEngineBuilder>();
    services.AddFiftyOne(Configuration);
    ...
  2. Configure the server to use the Pipeline which has just been set up.
    public class Startup
    {
    ...
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    app.UseFiftyOne();
    ...
  3. Inject the IFlowDataProvider into a controller.
    public class HomeController : Controller
    {
    private IFlowDataProvider _flow;
    public HomeController(IFlowDataProvider flow)
    {
    _flow = flow;
    }
    ...
    }
  4. Pass the results contained in the flow data to the view.
    public class HomeController : Controller
    {
    ...
    public IActionResult Index()
    {
    var data = _flow.GetFlowData().Get<IDeviceData>();
    return View(data);
    }
    ...
  5. Display device details in the view.
    @model FiftyOne.DeviceDetection.IDeviceData
    ...
    var hardwareVendor = Model.HardwareVendor;
    ...
    Hardware Vendor: @(hardwareVendor.HasValue ? hardwareVendor.Value : $"Unknown ({hardwareVendor.NoValueMessage})")<br />
    ...

Controller

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using FiftyOne.Pipeline.Web.Services;
using FiftyOne.Pipeline.JsonBuilder.Data;
{
public class HomeController : Controller
{
private IFlowDataProvider _flow;
public HomeController(IFlowDataProvider flow)
{
_flow = flow;
}
public IActionResult Index()
{
var data = _flow.GetFlowData().Get<IDeviceData>();
return View(data);
}
}
}

View

@model FiftyOne.DeviceDetection.IDeviceData
@{
ViewData["Title"] = "Device detection example";
var hardwareVendor = Model.HardwareVendor;
var hardwareName = Model.HardwareName;
var deviceType = Model.DeviceType;
var platformVendor = Model.PlatformVendor;
var platformName = Model.PlatformName;
var platformVersion = Model.PlatformVersion;
var browserVendor = Model.BrowserVendor;
var browserName = Model.BrowserName;
var browserVersion = Model.BrowserVersion;
var screenWidth = Model.ScreenPixelsWidth;
var screenHeight = Model.ScreenPixelsHeight;
}
<h2>Example</h2>
<div id="content">
<p>
The following values are determined by sever-side device detection
on the first request:
</p>
<p>
<b>Hardware Vendor:</b> @(hardwareVendor.HasValue ? hardwareVendor.Value : $"Unknown ({hardwareVendor.NoValueMessage})")<br />
<b>Hardware Name:</b> @(hardwareName.HasValue ? string.Join(", ", hardwareName.Value) : $"Unknown ({hardwareName.NoValueMessage})")<br />
<b>Device Type:</b> @(deviceType.HasValue ? deviceType.Value : $"Unknown ({deviceType.NoValueMessage})")<br />
<b>Platform Vendor:</b> @(platformVendor.HasValue ? platformVendor.Value : $"Unknown ({platformVendor.NoValueMessage})")<br />
<b>Platform Name:</b> @(platformName.HasValue ? platformName.Value : $"Unknown ({platformName.NoValueMessage})")<br />
<b>Platform Version:</b> @(platformVersion.HasValue ? platformVersion.Value : $"Unknown ({platformVersion.NoValueMessage})")<br />
<b>Browser Vendor:</b> @(browserVendor.HasValue ? browserVendor.Value : $"Unknown ({browserVendor.NoValueMessage})")<br />
<b>Browser Name:</b> @(browserName.HasValue ? browserName.Value : $"Unknown ({browserName.NoValueMessage})")<br />
<b>Browser Version:</b> @(browserVersion.HasValue ? browserVersion.Value : $"Unknown ({browserVersion.NoValueMessage})")<br />
<b>Screen width (pixels):</b> @(screenWidth.HasValue ? screenWidth.Value.ToString() : $"Unknown ({screenWidth.NoValueMessage})")<br />
<b>Screen height (pixels):</b> @(screenHeight.HasValue ? screenHeight.Value.ToString() : $"Unknown ({screenHeight.NoValueMessage})")
</p>
<p>
The information shown below is determined from JavaScript running on the client-side that is able to obtain additional evidence. If no additional information appears then it may indicate an external problem such as JavaScript being disabled in your browser.
</p>
<p>
Note that the 'Hardware Name' field is intended to illustrate detection of Apple device models as this cannot be determined server-side. This can be tested to some extent using most emulators such as those in the 'developer tools' menu in Google Chrome. However, using real devices will result in more precise model numbers.
</p>
</div>
@await Component.InvokeAsync("FiftyOneJS")
<script>
// This function will fire when the JSON data object is updated
// with information from the server.
// The sequence is:
// 1. Response contains JavaScript properties 'ScreenPixelsHeightJavaScript', 'ScreenPixelWidthJavaScript' and 'JavaScriptHardwareProfile'. These are executed on the client.
// 2. This triggers another call to the webserver that includes the evidence gathered by these JavaScript properties.
// 3. The web server responds with new JSON data that contains the updated property values based on the new evidence.
// 4. The JavaScript integrates the new JSON data and fires the 'complete' callback below.
window.onload = function () {
fod.complete(function (data) {
let fieldValues = [];
fieldValues.push([ "Hardware Name: ", data.device.hardwarename.join(", ") ]);
fieldValues.push([ "Screen width (pixels): ", data.device.screenpixelswidth ]);
fieldValues.push([ "Screen height (pixels): ", data.device.screenpixelsheight ]);
displayValues(fieldValues);
});
function displayValues(fieldValues) {
var para = document.createElement("p");
fieldValues.forEach(function (entry) {
var br = document.createElement("br");
var bold = document.createElement('b');
var fieldname = document.createTextNode(entry[0]);
var fieldvalue = document.createTextNode(entry[1]);
bold.appendChild(fieldname);
para.appendChild(bold);
para.appendChild(fieldvalue);
para.appendChild(br);
});
var element = document.getElementById("content");
element.appendChild(para);
}
}
</script>

Startup

/* *********************************************************************
* This Original Work is copyright of 51 Degrees Mobile Experts Limited.
* Copyright 2019 51 Degrees Mobile Experts Limited, 5 Charlotte Close,
* Caversham, Reading, Berkshire, United Kingdom RG4 7BY.
*
* This Original Work is licensed under the European Union Public Licence (EUPL)
* v.1.2 and is subject to its terms as set out below.
*
* If a copy of the EUPL was not distributed with this file, You can obtain
* one at https://opensource.org/licenses/EUPL-1.2.
*
* The 'Compatible Licences' set out in the Appendix to the EUPL (as may be
* amended by the European Commission) shall be deemed incompatible for
* the purposes of the Work and the provisions of the compatibility
* clause in Article 5 of the EUPL shall not apply.
*
* If using the Work as, or as part of, a network application, by
* including the attribution notice(s) required under Article 5 of the EUPL
* in the end user terms of the application under an appropriate heading,
* such notice(s) shall fulfill the requirements of that article.
* ********************************************************************* */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using FiftyOne.Common.Wrappers.IO;
using FiftyOne.Pipeline.Core.FlowElements;
using FiftyOne.Pipeline.Engines.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddTransient<HttpClient>();
services.AddSingleton<IFileWrapper, FileWrapper>();
services.AddSingleton<IFileSystem, RealFileSystem>();
services.AddSingleton<Func<TimerCallback, object, TimeSpan, Timer>>(
(callback, state, dueTime) =>
{
return new Timer(callback, state, (long)dueTime.TotalMilliseconds, Timeout.Infinite);
});
// Add the DataUpdate Service
services.AddSingleton<IDataUpdateService, DataUpdateService>();
services.AddSingleton<DeviceDetectionHashEngineBuilder>();
services.AddFiftyOne(Configuration);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseFiftyOne();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}