How to get base uri of site on application start? - asp.net

I have asp.net mvc application. I was using the following code to get base URI inside controller.
var baseApplicationUrl = string.Format("{0}://{1}", HttpContext.Current.Request.Url.Scheme, HttpContext.Current.Request.Url.Authority);
this was working fine.
Is there a way to construct baseuri in Application_Start()?
In application start method HttpContext.Current.Request will throw exception
Update 1
I have a UISettings class which holds some links. The base URI of these links would be different based on how the application is hosted. For example it could be http://www.example.com/home/index or https://www.example.com/home/index or http://www.example.com/subdomain/home/index. so home/index has different base uri depends on how its hosted.
I understand that the request is not available on application start. But i wanted to load the UISettings on application start so i can register with DI framework as singleton instance.
public class UISettings
{
public string Link1 {get;set;}
public string Link2 {get;set;}
public static UiSettings Load()
{
// need to get baseURI here???
var settings = new UISettings();
settings.Link1 = baseURI + "/home/index";
return settings;
}
}
and then register with DI framework as singleton on application start so i can inject it in any class latter
container.RegisterInstance<UISettings>(UiSettings.Load());

I'm not sure what you are trying to accomplish here. At Application_Start() stage Request is not constructed yet, so I think the earliest time you can get URI from Current Request is in Aplication_BeginRequest(), before then it is your starting page that can be assigned in and used from WebConfig file.

Related

.NET Core 3 using IUrlHelper in ControllerBase

I have a NET Core 3.1 REST API in and have configured the start up with services.AddControllers since I don't need views etc; it is also using endpoint routing.
However, I cannot generate the urls for newly created resources since the ControllerBase.Url property is null.
The code looks a bit like this..
pubic IActionResult Post(OrderRequest request)
{
var order = service.CreateOrder(request);
var url = Url.Link("Get", new { id = order.Id });
return new CreatedResult(url, result);
}
So the questions are:
Should I be injecting LinkGenerator instead.
How can I change startup so that ControllerBase.Url is populated
Is this a bug?

It is possible to retrieve host address in application service in abp framework?

It is possible to have host address in app services?
For example we want send email to customer with specific link point to site address. How is this possible?
This came up via Google & the existing answer didn't really help. I don't necessarily agree that app services are the wrong domain for this; in ABP for example, a service is closely connected to a controller and services usually only exist in order to service web requests there. They often execute code in an authorised state that requires a signed-in user, so the whole thing is happening in the implicit domain context of an HTTP request/response cycle.
Accordingly - https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-2.2#use-httpcontext-from-custom-components
Add services.AddHttpContextAccessor(); to something like your Startup.cs - just after wherever you already call services.AddMvc().
Use dependency injection to get hold of an IHttpContextAccessor in your service - see below.
Using constructor-based dependency injection, we add a private instance variable to store the injected reference to the context accessor and a constructor parameter where the reference is provided. The example below has a constructor with just that one parameter, but in your code you probably already have a few in there - just add another parameter and set _httpContextAccessor inside the constructor along with whatever else you're already doing.
using HttpContext = Microsoft.AspNetCore.Http.HttpContext;
using IHttpContextAccessor = Microsoft.AspNetCore.Http.IHttpContextAccessor;
// ...
public class SomeService : ApplicationService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public SomeService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
}
Now service code can read the HTTP context and from there things like the HTTP request's host and port.
public async Task<string> SomeServiceMethod()
{
HttpContext context = _httpContextAccessor.HttpContext;
string domain = context.Request.Host.Host.ToLowerInvariant();
int? port = context.Request.Host.Port;
// ...
}
HttpContext.Current.Request.Url
can get you all the info on the URL. And can break down the url into its fragments.

Get url from java class

I have this singleton class which will start when the application starts and the method invokes itself for every 30 seconds.
#Singleton
#Startup
public class myClass{
#Schedule(second="*/30", minute="*", hour="*")
public void serviceRequest(){
String url = "";
//send request
}
}
the url will be something like http://localhost:7001/webapp/rest/tasks/mytask. I don't want to hardcode the url. Instead, I want to somehow get that from the system (or somewhere). I've tried injecting resource like HttpServletRequest but that didn't work.
Thanks in advance.
In case you're using JAX-RS, then this will work:
#RequestScoped #Path("tasks")
public class TaskResource {
#GET #Path("{id}")
public Response getTask(#PathParam("id") String id) {
/* whatever */
}
}
URI uri = UriBuilder.fromResource(TaskResource.class)
.segment("{id}").build("mytask");
The url will be provided by an external service so I dont need to worry about host and port number since ill get full url to that rest service. Because the service isn't available so I made an in house rest service to test my functionality. I guess I will harcode the url for now.

Referencing in the context of asp.net Identity 2.0 separation

I try to separate one of my API projects into three different layers.
The API
Data access(repos + uow)
Data Entities
The API is using Asp.net Identity 2.0 with code from a sample I installed, just enough to work with OAuth Authorization.
However, When I do this separation, sometimes I get an error telling me that I need to reference the third layer(entities) from my first layer. And I can't figure out why. That would break the whole purpose of the separation, right?
For example, when I try to replace this line(from the API layer in Startup.Auth.cs, ConfigureAuth method)
app.CreatePerOwinContext(ApplicationDbContext.Create);
With
app.CreatePerOwinContext(uow.CreateDbContext())
A method that returns a new instance of the ApplicationDbContext.
I would expect that context to be returned from my second layer, where my UnitOfWork is(which in turn gets the ApplicationDbContext from the data layer).
Could someone please explain how this works?
To solve your issue you need to start use Interfaces and any DI-framework. Here I can provide you with the code if you want to start using AutoFac (https://code.google.com/p/autofac/wiki/WebApiIntegration).
When you installed AutoFac to your solution through Nuget. Add this part of code in your Global.asax.cs file.
protected void Application_Start()
{
...
SetupAutoFac();
...
}
private static void SetupAutoFac()
{
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Setup();
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
Create this part of code in your BLL-layer:
public static class AutoFacConfiguration
{
public static IContainer Setup(this ContainerBuilder builder)
{
REGISTER ALL YOUR SERVICES AND UOW HERE
return builder.Build();
}
}
After this you can inject every services Interface to your ApiControllers, and the the WebAPi will only have a reference to your BLL-layer or to the layer where you put all your interfaces.

Get an instance of WebApi UrlHelper from inside an Mvc Action

I am running WebApi and Mvc from within the same project (so they are in-process). Mvc mostly for serving assets (pages and generated downloads) and web api for ajax data requests.
In order to be RESTish, most of the WebApi requests include a set of links where are generated by the following class:
public class ApiLinkMaker
{
public ApiLinkMaker(UrlHelper url, string authority) {
this.url = url;
this.authority = authority;
}
public ApiLinkMaker(ApiController controller)
: this(controller.Url, controller.Request.RequestUri.Authority) { }
public string MakeLink(string controller, string id) {
return "//" + authority + url.Route("DefaultApi", new { controller = controller, id = id });
}
}
There's a few other methods on there, but this is really the core of things and it works fine.
Now I want to optimize a particular page. Where previously I had two requests
Download the html
Do an Ajax query to get some data (and some links)
Now I realize that for optimization purposes it is better to do just one in this case.
Download the html with the data already JSON embedded into it.
The problem is that since the html is being generated by Mvc, I cannot create an Api UrlHelper that seems to work.
I tried
var url = new UrlHelper(new HttpRequestMessage(verb, controller.Request.Url.AbsoluteUri));
if (!url.Request.Properties.ContainsKey(HttpPropertyKeys.HttpConfigurationKey)) //http://stackoverflow.com/questions/11053598/how-to-mock-the-createresponset-extension-method-on-httprequestmessage
url.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
But this still blows up
System.ArgumentException was unhandled by user code
HResult=-2147024809
Message=A route named 'DefaultApi' could not be found in the route collection.
Parameter name: name
Source=System.Web.Http
ParamName=name
StackTrace:
at System.Web.Http.HttpRouteCollection.GetVirtualPath(HttpRequestMessage request, String name, IDictionary`2 values)
at System.Web.Http.Routing.UrlHelper.GetHttpRouteHelper(HttpRequestMessage request, String routeName, IDictionary`2 routeValues)
at System.Web.Http.Routing.UrlHelper.GetHttpRouteHelper(HttpRequestMessage request, String routeName, Object routeValues)
at System.Web.Http.Routing.UrlHelper.Route(String routeName, Object routeValues)
at MyProject.Models.ApiLinkMaker.MakeLink(String controller, String id) in w:\MyProject\Models\ApiLinkMaker.cs:line 42
...
This leads me to think that I'm going about this wrong - that I need to create the url helper from the api routing configuration somehow.
Why create one? There is an instance of the UriHelper exposed as a property on both the MVC Controller and ApiController classes.
public ActionResult Index()
{
string url = Url.RouteUrl("DefaultApi", new {httproute = "", controller = "test"});
return View();
}
Edit: Updated code. While the url helpers are different you can use the MVC url helper to resolve the web api url.
Edit2: The correct method to use if you want to get webapi routes from an Mvc UrlHelper is
string url = Url.HttpRouteUrl("DefaultApi", new {httproute = "", controller = "test"});

Resources