Wie kann ich die Basis meiner Site in ASP.NET Core abrufen?

75

Angenommen, meine Website wird im Ordner " mywebsite " von www.example.com gehostet und ich besuche https://www.example.com/mywebsite/home/about .

Wie erhalte ich den Basis-URL-Teil in einem MVC-Controller? Der Teil, den ich suche, ist https://www.example.com/mywebsite

Das hier aufgeführte Beispiel funktioniert nicht, da wir in ASP.NET Core keinen Zugriff auf Request.Url haben

jao
quelle
@VSO Wenn Sie sich die vom OP verknüpfte Antwort ansehen, sehen Sie eine aktualisierte Version für Core, die Sie in einen Dienst konvertieren können sollten, damit Sie während des Umfangs einer Anfrage überall in der App auf die Anfrage zugreifen können. stackoverflow.com/a/12144292/5233410 Die Antwort in dieser Frage ist korrekt. Was verstehst Du nicht?
Nkosi

Antworten:

119

Sie sollten immer noch in der Lage sein, das zusammenzusetzen, was Sie brauchen. Sie haben Zugriff auf das Anforderungsobjekt, wenn Ihr Controller von erbt Controller.

Wenn Sie VS2017 verwenden, starten Sie eine neue ASPNet Core MVC-App und ersetzen Sie den Homecontroller durch:

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    public IActionResult About()
    {
        ViewData["Message"] = $"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}";

        return View();
    }

    public IActionResult Contact()
    {
        ViewData["Message"] = "Your contact page.";

        return View();
    }

    public IActionResult Error()
    {
        return View();
    }
}

Ich habe nur einige Dinge hinzugefügt, die Sie an der "About" -Methode interessieren könnten, aber Sie sollten den Rest der Anforderungsklasse untersuchen, damit Sie wissen, was noch verfügbar ist.

Wie @Tseng hervorhob, haben Sie möglicherweise ein Problem, wenn Sie Kestrel hinter IIS oder Azure App Service ausführen. Wenn Sie jedoch das IISIntegration-Paket oder das AzureAppServices-Paket verwenden (indem Sie das Nuget-Paket installieren und es in Program.cs zu Ihrem WebHostBuilder hinzufügen), tritt ein Problem auf sollte diese Header an Sie weiterleiten. In Azure funktioniert das hervorragend, da ich manchmal Entscheidungen treffen muss, die darauf basieren, welchen Hostnamen sie treffen. Die IIS / Azure-Pakete leiten auch die ursprüngliche Remote-IP-Adresse weiter, die ich protokolliere.

NPNelson
quelle
3
Das sollte Request.Scheme + ": //" + Request.Host + Request.PathBase
Tratcher
3
Ich habe meine Antwort aktualisiert, um PathBase anstelle von Path zu verwenden . Vielen Dank an Tratcher für den Hinweis.
NPNelson
1
Ich möchte darauf hinweisen, wie schrecklich diese Idee ist. Ein Benutzer kann "Url.Request" ändern. Verwenden Sie dies nicht in der Nähe von Benutzerinformationen. Stellen Sie sich eine gut gestaltete Anfrage "Passwort vergessen" vor.
Johnrom
Funktioniert, wenn ich .Value.ToString () $ "{this.Request.Scheme} anhänge: // {this.Request.Host.Value.ToString ()} {this.Request.PathBase.Value.ToString ()}";
Hubert17
In Anbetracht dessen denke ich, dass es tatsächlich ziemlich einfach ist, diesen Wert zu speichern und später zu verwenden, ohne zu wissen, dass er ursprünglich aus (möglicherweise böswilligen) Benutzereingaben stammt. Ich habe eine Whitelist implementiert, um dies zu mildern. Alternativ können Clients, die diese Basis-URL verwenden, auch eine Herausforderung an den Server stellen.
Jmathew
44

Wenn Sie dies irgendwo in Ihrer App benötigen, sollten Sie eine Middleware erstellen. Definieren Sie Ihre statische Klasse und Ihre Erweiterungsmethode zum Hinzufügen der Middleware zur Service-Pipeline wie folgt.

public class MyHttpContext
{
    private static IHttpContextAccessor m_httpContextAccessor;

    public static HttpContext Current => m_httpContextAccessor.HttpContext;

    public static string AppBaseUrl => $"{Current.Request.Scheme}://{Current.Request.Host}{Current.Request.PathBase}";

    internal static void Configure(IHttpContextAccessor contextAccessor)
    {
        m_httpContextAccessor = contextAccessor;
    }
}

public static class HttpContextExtensions
{
    public static void AddHttpContextAccessor(this IServiceCollection services)
    {
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    }

    public static IApplicationBuilder UseHttpContext(this IApplicationBuilder app)
    {
        MyHttpContext.Configure(app.ApplicationServices.GetRequiredService<IHttpContextAccessor>());
        return app;
    }
}

In diesem Fall ist es möglicherweise etwas überflüssig, den HttpContext verfügbar zu machen, aber ich finde es sehr hilfreich.

Sie würden es dann der Pipeline in Ihrer Configfure-Methode hinzufügen, die sich in Startup.cs befindet

app.UseHttpContext()

Von dort aus ist es einfach, es überall in Ihrem Code zu verwenden.

var appBaseUrl = MyHttpContext.AppBaseUrl;
rauben
quelle
5
Dies scheint zu funktionieren, wenn Sie MyHttpContext.AppBaseUrl vom Controller aus aufrufen. Ich benötige die Basis-URL beim Start direkt nach app.UseHttpSettings (). HttpContext scheint dort null zu sein. Irgendwelche Gedanken? Danke
Wer auch immer
1
Stellen Sie sicher, dass Sie services.AddHttpContextAccessor () in der ConfigureServices-Methode aufrufen.
Rob
3
Vielen Dank. Immer noch das gleiche. Ich habe irgendwo gelesen, dass die Art und Weise, wie .NET Core gehostet wird, die Serverinformationen erst dann enthält, wenn es vollständig gestartet ist. Ich habe versucht, es aus StartUp heraus zu bekommen.
Wer auch immer
@Wer auch immer Wie haben Sie das Problem gelöst? Ich stecke nur da drüben fest.
Sruthi Varghese
2
@SruthiVarghese Ich glaube nicht, dass Sie die Host-URL vom Start an auflösen können. Meines Wissens nach sind .NET Core alle Konsolen-Apps. Ihr Startup entscheidet, wie sie gehostet werden. So kann genau derselbe Code wie Konsole, iisexpress, iis usw. ausgeführt werden. Außerdem befindet sich in PROD häufig ein Proxy / Gateway vor Ihren Servern. Ich denke, der einfachste Weg ist, einfach einen Konfigurationswert für die App-Basis-URL zu erstellen.
Wer auch immer
2

Die NPNelson-Antwort funktioniert, wenn mit .Value.ToString ()

var baseUrl = $"{this.Request.Scheme}://{this.Request.Host.Value.ToString()}{this.Request.PathBase.Value.ToString()}";
hubert17
quelle
4
ToStringist hier nicht hilfreich. Es wird automatisch von string.Formatbereits gemacht.
Patrick Hofman
1
var baseUrl = Request.GetTypedHeaders().Referer.ToString();

Auf diese Weise können Sie die Basis-URL-Informationen erfassen.

So konnte ich es in der Asp. Net Core 3.1-Version bekommen.

Sie können über den folgenden Link auf die Ressource zugreifen.

Referenz

Ahmet Tınastepe
quelle
0
using Microsoft.AspNetCore.Http;    

public void ConfigureServices(IServiceCollection services)
{
     services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
    
    
public AccountController(IHttpContextAccessor httpContextAccessor)
{
     var request = httpContextAccessor.HttpContext.Request;
     var domain = $"{request.Scheme}://{request.Host}";
     //domain => https://varunsoft.in
}
Varun
quelle
-1
string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Content("~"));

Weitere Informationen finden Sie hier: Wie kann ich die Basis-URL meiner Webanwendung in ASP.NET MVC abrufen?

Oren Tamam
quelle
10
Ich kann mich irren, aber ich glaube, dass dies in .NET Core nicht funktioniert. Ich bin hierher gekommen, weil Request.Url nicht verfügbar ist.
Josh G
Funktioniert nicht in ASP.Net Core. OP fragt speziell nach ASP.Net Core
Harindaka