I'm implementing email sending module and need to build URLs. My intention was to use IUrlHelper, but I really struggle to build this object due to the enormous amount of dependencies it needs to provide.
At the current moment I'm at this step:
ActionContext actionCtx = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
_urlHelper = new UrlHelper(actionCtx);
but constructed that way urlHelper
still fails with an exception when trying to build URL.
Exception is:
Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) at System.Collections.Generic.List`1.get_Item(Int32 index) at Microsoft.AspNetCore.Mvc.Routing.UrlHelper.get_Router()
So probably now it's required to create and set IRouter
instance, but as I could see it's again required to set tons of deps
So how this should be done correctly?
In ASP.NET Core, if we need to access the HttpContext in service, we can do so with the help of IHttpContextAccessor interface and its default implementation of HttpContextAccessor. It's only necessary to add this dependency if we want to access HttpContext in service.
By specifying the protocol and host, the result is now "https://your-website/Home/Privacy" . However, if you omit the host parameter but keep the protocol parameter, the result will still be an absolute URL, because the host parameter will default to the host used for the current HTTP request.
HttpContext encapsulates all information about an individual HTTP request and response. An HttpContext instance is initialized when an HTTP request is received. The HttpContext instance is accessible by middleware and app frameworks such as Web API controllers, Razor Pages, SignalR, gRPC, and more.
There are two sets of methods or extension methods that can be used: GetPathBy*** - used to get relative paths. GetUriBy*** - used to get absolute URI.
As you've discerned, it's going to be next to impossible to achieve this in a completely disconnected library. More to the point, you need routes to even make it worthwhile, which are going to be cleanly confined in a separate web application, your library would have to have a hard dependency on to access. In case it's not obvious, that would be a very poor design choice to make.
I think you need to step back and re-evaluate. If your goal is to simply send an email through an external process, then whatever is scheduling a task there (presumably your web application) should pass it the information it needs for that email, including any URLs. That shifts the responsibility of creating those URLs away from your email library (which really shouldn't have this responsibility anyways - do one thing and do it well) back to a source that likely already has the necessary ability.
If this cannot be done for some reason. I'd say your next best bet is to set up one or more endpoints on the web application you're trying to generate URLs for and have those return the URLs you need and/or any other additional information the email library needs to send an email. This still externalizes the email sending functionality, but gives your library a clean way to get access to information from the web application when it needs it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With