There is no Esri Proxy (https://github.com/Esri/resource-proxy) for ASP.NET Core. However, it's very easy to implement a simple ASP.NET HTTP proxy. The solution below is not a full replacement of proxy.ashx
but elaborates an idea how to handle CORS issues and login credential in a webmap application.
Note: If you have authorization and access to configure the webserver and/or configure ArcGIS Online services, there may be other alternatives (https://github.com/Esri/resource-proxy#alternatives). In addition, it may be worth to consider a dedicated proxy server (depending on the traffic).
The NuGet Package AspNetCore.Proxy
(https://github.com/twitchax/AspNetCore.Proxy) must be installed.
Extend appsettings.json
with a key "Proxy"
:
{
"Proxy": {
"AcceptedUrls": [
"https://www.geomo.ch",
"https://www.moosetraveller.ch"
],
"MailService": {
"Url": "https://www.geomo.ch/api/tracking",
"ApiKey": "12345"
}
}
}
namespace Geomo {
public class ProxyConfig {
public string[] AcceptedUrls { get; set; }
public ParcelServiceConfig ParcelService { get; set; }
}
public class MailServiceConfig {
public string ApiKey { get; set; }
public string Url { get; set; }
}
}
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
var proxyConfig = new ProxyConfig();
Configuration.GetSection("Proxy").Bind(proxyConfig);
services.AddSingleton(proxyConfig);
// ...
services.AddProxies();
// ...
}
// ...
public class ProxyController : ControllerBase
{
private readonly ProxyConfig _configuration;
private readonly ILogger<ProxyController> _logger;
private readonly HttpProxyOptions _httpOptions;
public ProxyController(ProxyConfiguration configuration, ILogger<ProxyController> logger)
{
_configuration = configuration;
_logger = logger;
_httpOptions = HttpProxyOptionsBuilder.Instance
.WithHandleFailure((httpContext, exception) =>
{
_logger.LogError(exception, $"Proxy Error: {nameof(exception)}");
return Task.CompletedTask;
})
.Build();
}
// proxy?https://www.moosetraveller.ch
// => https://www.moosetraveller.ch
[Route("proxy")]
public Task HandleProxyRequest()
{
var query = HttpUtility.ParseQueryString(Request.QueryString.Value).ToString();
if (_configuration.AcceptedUrls.Any(url => query.StartsWith(url)))
{
return this.HttpProxyAsync(query, _httpOptions);
}
HttpContext.Response.StatusCode = 500;
return HttpContext.Response.WriteAsync($"URL {query} is not accepted.");
}
// example with route parameter:
// api/external/parcels/57896
// => https://www.geomo.ch/api/tracking?tracking=57896&type=letter&apiKey=12345
[Route("api/external/parcels/{trackingNumber}")]
public Task GetParcel(string trackingNumber) {
var query = HttpUtility.ParseQueryString("?");
query["tracking"] = trackingNumber;
query["type"] = "parcel";
query["apiKey"] = _configuration.ParcelService.ApiKey;
return this.HttpProxyAsync($"{_configuration.ParcelService.Url}?{query}", _httpOptions);
}
// example with query string:
// api/external/letters?trackingNumber=56874
// => https://www.geomo.ch/api/tracking?tracking=57896&type=letter&apiKey=12345
[Route("api/external/letters")]
public Task GetLetter() {
var query = HttpUtility.ParseQueryString(Request.QueryString.Value);
query["type"] = "letter";
query["apiKey"] = _configuration.ParcelService.ApiKey;
return this.HttpProxyAsync($"{_configuration.ParcelService.Url}?{query}", _httpOptions);
}
}