Jak mogę uzyskać podstawowy adres URL mojej aplikacji internetowej w ASP.NET MVC?

300

Jak mogę szybko ustalić, jaki jest główny adres URL mojej aplikacji ASP.NET MVC? To znaczy, jeśli IIS jest skonfigurowany do obsługi mojej aplikacji pod adresem http://example.com/foo/bar , to chciałbym móc uzyskać ten adres URL w niezawodny sposób, który nie wymaga pobierania bieżącego adresu URL z prośbę i posiekaj ją w delikatny sposób, który zepsuje się, jeśli zmienię trasę.

Powodem, dla którego potrzebuję podstawowego adresu URL, jest to, że ta aplikacja internetowa wywołuje inną, która potrzebuje katalogu głównego do aplikacji internetowej dzwoniącego do celów wywołania zwrotnego.

Benjamin Pollack
źródło

Odpowiedzi:

399

Zakładając, że masz dostępny obiekt żądania, możesz użyć:

string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Content("~"));

Jeśli nie jest dostępny, możesz do niego dotrzeć poprzez kontekst:

var request = HttpContext.Current.Request
tghw
źródło
8
Co to jest urlHelper.Content("~")? Jak utworzyć zdefiniować urlHelper? Dzięki!
Maxim Zaslavsky,
31
@Maxim, możesz prawdopodobnie zastąpić Url.Content ("~")
UpTheCreek
13
Co skończyło się na użyciu:var request = HttpContext.Current.Request; urlBase = string.Format("{0}://{1}{2}", request.Url.Scheme, request.Url.Authority, (new System.Web.Mvc.UrlHelper(request.RequestContext)).Content("~"));
Peter
7
Do MVC 4 używamControllerContext.RequestContext.HttpContext.Request
wiersz 1
7
@Url.Content("~")rozwiązuje na "/", który nie jest podstawowym adresem URL.
Andrew Hoffman
114

Więc żaden z wymienionych tutaj nie działał dla mnie, ale korzystając z kilku odpowiedzi, dostałem coś działającego:

public string GetBaseUrl()
{
    var request = HttpContext.Current.Request;
    var appUrl = HttpRuntime.AppDomainAppVirtualPath;

    if (appUrl != "/") 
        appUrl = "/" + appUrl;

    var baseUrl = string.Format("{0}://{1}{2}", request.Url.Scheme, request.Url.Authority, appUrl);

    return baseUrl;
}

Aktualizacja dla ASP.NET Core / MVC 6:

ASP.NET Coresprawia, że ​​ten proces jest nieco bardziej bolesny, szczególnie jeśli jesteś głęboko w kodzie. Masz 2 opcje, aby uzyskać dostęp doHttpContext

1) Przekaż go ze swojego controller:

var model = new MyClass(HttpContext);

następnie w model:

private HttpContext currentContext;

public MyClass(HttpContext currentContext)
{
    this.currentContext = currentContext;
}

2) Być może najprostszym sposobem jest wstrzyknięcie go do twojej klasy, co zaczyna się od zarejestrowania typów w twoim Startup:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    services.AddTransient<MyClass, MyClass>();
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

następnie wstrzyknij to dla ciebie w ten sposób:

private HttpContext currentContext;

public MyClass(IHttpContextAccessor httpContextAccessor)
{
    currentContext = httpContextAccessor.HttpContext;
}

w obu przypadkach zaktualizowano dla .NET Core GetBaseUrl():

public string GetBaseUrl()
{
    var request = currentContext.Request;

    var host = request.Host.ToUriComponent();

    var pathBase = request.PathBase.ToUriComponent();

    return $"{request.Scheme}://{host}{pathBase}";
}
Serj Sagan
źródło
Gdzie umieściłeś tę metodę?
Josh Dean
3
To naprawdę zależy od tego, jak często musisz go używać ... jeśli jest to umowa jednorazowego użytku, po prostu umieść ją w klasie, w której potrzebujesz tych danych, jeśli przewidujesz użycie jej w wielu klasach w Twojej aplikacji, to używam folder wywoływany Helpersw bazie mojej aplikacji, mam staticklasę o nazwie Staticsi umieszczam tam funkcje takie jak wyżej ... tylko upewnij się, że zmieniłeś powyższe z public string GetBaseUrl()napublic static string GetBaseUrl()
Serj Sagan
Jako aktualizację, nie używam już klasy o nazwie Statics, zamiast tego podzieliłem ją na bardziej konkretne zastosowania, więc w tym przypadku trafiłoby to do mojej UrlHelperklasy
Serj Sagan
1
Ze wszystkich opcji, które znalazłem, jest to jedyna, która faktycznie działała dla mnie. To jest twój numer 2. Wielkie dzięki!
adeldegan
2
Poprosiłem o to, ponieważ jako jedyny wspomniał o PathBase, a dokładnie tego potrzebowałem. Dzięki!
Dave
69

W kodzie:

Url.Content("~/");

Składnia Razor MVC3:

@Url.Content("~/")
mxasim
źródło
11
Jest to przydatne do używania na stronach Razor, ale jeśli próbujesz przekazać adres URL do zewnętrznego źródła, nie da ci pełnego adresu URL.
krillgar
5
To nie działa Po prostu doda /zamiast rzeczywistej nazwy.
Mrchief
2
Gdzie jest Code, w którym Urlpomocnik jest dostępny od samego początku? Może tylko w Controller. Na pewno nie w ViewModelżadnym innym classmiejscu, w którym możesz tego potrzebować.
Serj Sagan
43

Może jest to rozszerzenie lub modyfikacja zamieszczonych tutaj odpowiedzi, ale używam po prostu następującego wiersza i działa:

Request.Url.GetLeftPart(UriPartial.Authority) + Url.Content("~")

Kiedy moja ścieżka to: http://host/iis_foldername/controller/action
wtedy otrzymuję:http://host/iis_foldername/

Bronek
źródło
26

Poniższy fragment kodu działa dobrze w MVC4 i nie wymaga HttpContextdostępnego:

System.Web.HttpRuntime.AppDomainAppVirtualPath
użytkownik666142
źródło
Wydaje się również działać w MVC3. Używam go jQuery.load()do konstruowania adresu URL kontrolera i działania, które chcę wywołać: $('#myplaceholder').load('@(Html.Raw(HttpRuntime.AppDomainAppVirtualPath))/MyController/MyAction', ...);
Kjell Rilbe,
dlaczego chcesz to zrobić? zamiast dzwonić na Url.Action?
BlackTigerX,
4
Nie działa po wdrożeniu na platformie Azure. W tym scenariuszu działają odpowiedzi lepiej ocenione.
Jeff Dunlop
25

Sztuka polegania na IIS polega na tym, że powiązania IIS mogą różnić się od twoich publicznych adresów URL (WCF patrzę na ciebie), szczególnie w przypadku maszyn produkcyjnych z wieloma bazami. Skłaniam się do użycia konfiguracji w celu jawnego zdefiniowania „podstawowego” adresu URL do celów zewnętrznych, ponieważ jest to zwykle bardziej skuteczne niż wyodrębnienie go z obiektu Request.

Wyatt Barnett
źródło
2
Dotyczy to również serwerów równoważących obciążenie lub serwerów proxy.
Ishmaeel
20

Użyj bezwzględnego podstawowego adresu URL. Działa zarówno z HTTP, jak i HTTPS.

new Uri(Request.Url, Url.Content("~"))
arni
źródło
15

To jest konwersja właściwości asp.net do MVC . Prawie wszystko polega na śpiewaniu i tańczeniu metodą root root.

Zadeklaruj klasę pomocnika:

namespace MyTestProject.Helpers
{
    using System.Web;

    public static class PathHelper
    {
        public static string FullyQualifiedApplicationPath(HttpRequestBase httpRequestBase)
        {
            string appPath = string.Empty;

            if (httpRequestBase != null)
            {
                //Formatting the fully qualified website url/name
                appPath = string.Format("{0}://{1}{2}{3}",
                            httpRequestBase.Url.Scheme,
                            httpRequestBase.Url.Host,
                            httpRequestBase.Url.Port == 80 ? string.Empty : ":" + httpRequestBase.Url.Port,
                            httpRequestBase.ApplicationPath);
            }

            if (!appPath.EndsWith("/"))
            {
                appPath += "/";
            }

            return appPath;
        }
    }
}

Stosowanie:

Aby użyć z kontrolera:

PathHelper.FullyQualifiedApplicationPath(ControllerContext.RequestContext.HttpContext.Request)

Aby użyć w widoku:

@using MyTestProject.Helpers

PathHelper.FullyQualifiedApplicationPath(Request)
Paul Zahra
źródło
1
To jedyna odpowiedź, która uwzględnia możliwość działania witryny na porcie innym niż 80. O ile mi wiadomo, wszystkie pozostałe odpowiedzi są niebezpieczne. Dzięki!
jebar8
12

W MVC _Layout.cshtml:

<base href="@Request.GetBaseUrl()" />

Tego używamy!

public static class ExtensionMethods
{
public static string GetBaseUrl(this HttpRequestBase request)
        {
          if (request.Url == (Uri) null)
            return string.Empty;
          else
            return request.Url.Scheme + "://" + request.Url.Authority + VirtualPathUtility.ToAbsolute("~/");
        }
}
katibaer
źródło
+1 za użycie <base>. Możesz także pominąć Schemat tak, aby działał z http lub https. Oznacza to, że możesz zacząć od adresu URL //.
Jess
5

Działa to dla mnie dobrze (także w przypadku modułu równoważenia obciążenia):

@{
    var urlHelper = new UrlHelper(Html.ViewContext.RequestContext);
    var baseurl = urlHelper.Content(“~”);
}

<script>
    var base_url = "@baseurl";
</script>

Zwłaszcza jeśli używasz niestandardowych numerów portów, użycie Request.Url.Authority na początku wydaje się być dobrym tropem, ale kończy się niepowodzeniem w środowisku LB.

Tadej Gregorcic
źródło
3

Możesz mieć metodę statyczną, która sprawdza HttpContext.Current i decyduje, którego adresu URL użyć (serwer programistyczny lub serwer na żywo) w zależności od identyfikatora hosta. HttpContext może nawet oferować łatwiejszy sposób na zrobienie tego, ale jest to pierwsza opcja, którą znalazłem i działa dobrze.

Adrian Grigore
źródło
3

Możesz użyć następującego skryptu w widoku:

<script type="text/javascript">
    var BASE_URL = '<%= ResolveUrl("~/") %>';
</script>
Andrus
źródło
3

W przypadku ASP.NET MVC 4 jest nieco inaczej:

string url = HttpContext.Request.Url.AbsoluteUri;
Fernando Vezzali
źródło
3

Działa to w ASP .NET MVC 4 W każdej akcji kontrolera, którą możesz napisać: 1stline pobiera cały adres URL + ciąg zapytania. Druga linia usuwa lokalną ścieżkę i zapytanie, ostatni symbol „/”. W trzecim wierszu dodaj symbol „/” na ostatniej pozycji.

Uri url = System.Web.HttpContext.Current.Request.Url;
string UrlLink = url.OriginalString.Replace(url.PathAndQuery,"");
UrlLink = String.Concat(UrlLink,"/" );
Muhammad Ashikuzzaman
źródło
3

w prostym HTML i ASP.NET lub ASP.NET MVC, jeśli używasz znacznika:

<a href="~/#about">About us</a>
Ravi Anand
źródło
3

W przypadku adresu URL z aliasem aplikacji, takim jak http://example.com/appAlias/ ... Możesz spróbować:

var req = HttpContext.Current.Request;
string baseUrl = string.Format("{0}://{1}/{2}", req.Url.Scheme, req.Url.Authority, req.ApplicationPath);
Jacek Gzel
źródło
3

Na samej stronie:

<input type="hidden" id="basePath" value="@string.Format("{0}://{1}{2}",
  HttpContext.Current.Request.Url.Scheme,
  HttpContext.Current.Request.Url.Authority,
  Url.Content("~"))" />

W javascript:

function getReportFormGeneratorPath() {
  var formPath = $('#reportForm').attr('action');
  var newPath = $("#basePath").val() + formPath;
  return newPath;
}

Działa to w moim projekcie MVC, mam nadzieję, że to pomoże

Andrew Day
źródło
@hemp Edytowałeś to, ale nie głosowałeś na to? Mam nadzieję, że punkty te są dla ciebie cenne
Andrew Day
To pytanie i powiązane z nim odpowiedzi nie były pomocne w mojej konkretnej sprawie, więc nie próbowałem ani nie głosowałem na żadne z nich. Zredagowałem ten, ponieważ zdarzyło mi się go zobaczyć i pomyślałem, że może być przyzwoitą odpowiedzią, jeśli został poprawnie sformatowany. Staram się być dobrym obywatelem.
konopie
Ponadto nie ma punktów reputacji za edycję odpowiedzi.
konopie
2

Umieszczam to w głowie mojego _Layout.cshtml

 <base href="~/" />
cineam źle zrozumiał
źródło
2

Może to lepsze rozwiązanie.

@{
   var baseUrl = @Request.Host("/");
}

za pomocą

<a href="@baseUrl" class="link">Base URL</a>
SM
źródło
1
Nie testowałem, ale wątpię, aby to zadziałało, gdy podstawowy adres URL jest wirtualny bezpośrednio. to znaczy. localhost / myApp
emragins
1

W przypadku MVC 4:

String.Format("{0}://{1}{2}", Url.Request.RequestUri.Scheme, Url.Request.RequestUri.Authority, ControllerContext.Configuration.VirtualPathRoot);
Remigijus Pankevičius
źródło
1

Poniższe działało dla mnie solidnie

var request = HttpContext.Request;
                        var appUrl = System.Web.HttpRuntime.AppDomainAppVirtualPath;

                        if (appUrl != "/")
                            appUrl = "/" + appUrl + "/";

                        var newUrl = string.Format("{0}://{1}{2}{3}/{4}", request.Url.Scheme, request.UrlReferrer.Host, appUrl, "Controller", "Action");
venu
źródło
1
@{
    var baseurl = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port + Url.Content("~");
}
@baseurl

--output http: // localhost: 49626 / TEST /

Jackdon Wang
źródło
1

To było moje rozwiązanie (przy użyciu .net core 3.1, w kontrolerze API):

string baseUrl = $"{Request.Scheme}://{Request.Headers.Where(h => h.Key == "Host").First().Value}";
Barnebyte
źródło
0

Wystarczy w jednej linii uzyskać BaseUrl

string baseUrl = new Uri(Request.Url, Url.Content("~")).AbsoluteUri;

//output example: https://stackoverflow.com
Zahid Tanveer
źródło
0

dodaj tę funkcję do klasy statycznej w projekcie, takiej jak klasa narzędziowa:

zawartość utility.cs :

public static class Utility
{
    public static string GetBaseUrl()
    {
        var request = HttpContext.Current.Request;
        var urlHelper = new UrlHelper(request.RequestContext);
        var baseUrl = $"{request.Url.Scheme}://{request.Url.Authority}{urlHelper.Content("~")}";
        return baseUrl;
    }
}

użyj tego kodu w dowolnym miejscu i ciesz się nim:

var baseUrl = Utility.GetBaseUrl();
DLMAN
źródło