Телефонуйте на UrlHelper у моделях на ASP.NET MVC


159

Мені потрібно генерувати деякі URL-адреси в моделі в ASP.NET MVC. Я б хотів назвати щось на зразок UrlHelper.Action (), який використовує маршрути для створення URL-адреси. Я не проти заповнення звичайних пробілів, таких як ім'я хоста, схема тощо.

Чи є якийсь метод, до якого я можу закликати це? Чи є спосіб побудувати UrlHelper?


1
Я думав про це сам, але майте на увазі, що Url.Action створить відносну URL-адресу. Будьте впевнені, що саме цього ви хочете.
Вівіан-Рівер

Відповіді:


277

Корисна порада, у будь-якій програмі ASP.NET ви можете отримати посилання на поточний HttpContext

HttpContext.Current

який походить від System.Web. Тому в додатку ASP.NET MVC буде працювати будь-де:

UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
url.Action("ContactUs"); // Will output the proper link according to routing info

Приклад:

public class MyModel
{
    public int ID { get; private set; }
    public string Link
    {
        get
        {
            UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
            return url.Action("ViewAction", "MyModelController", new { id = this.ID });
        }
    }

    public MyModel(int id)
    {
        this.ID = id;
    }
}

Виклик Linkвластивості на створеному об’єкті MyModel поверне дійсну URL-адресу для перегляду моделі на основі маршрутизації в Global.asax


Ви впевнені, що є HttpContext.Current.Request.RequestContext? Здається, у HttpContext.Current.Request немає RequestContext.
pupeno

1
Це дивно. Я щойно перевірив це рішення, і воно прекрасно працює. Я запускаю ASP.NET MVC 2 Preview 2, але, думаю, це працює у всіх версіях. Не впевнений, чому це не працює для вас. Ви створюєте клас поза проектом MVC? Також переконайтесь, що вони є usingдля обох System.WebіSystem.Web.Mvc
Омар

Я працюю над проектом ASP.NET MVC 1, я думав про те, щоб пропустити вставки, але у них є обидва.
pupeno

Не дуже впевнений, чому це не показується. Якщо хто-небудь інший міг би підтвердити, цього немає в ASP.NET MVC 1, це було б чудово. У мене встановлена ​​лише одна машина з VS2010 та MVC 2. Якщо вас цікавить, MVC RC 2 haacked.com/archive/2009/12/16/aspnetmvc-2-rc.aspx
Омар

6
Зауважте, що Request.RequestContex підтримується у .NET4 +
h - n

64

Мені подобається відповідь Омара, але це не працює для мене. Тільки для запису це рішення, яке я зараз використовую:

var httpContext = HttpContext.Current;

if (httpContext == null) {
  var request = new HttpRequest("/", "http://example.com", "");
  var response = new HttpResponse(new StringWriter());
  httpContext = new HttpContext(request, response);
}

var httpContextBase = new HttpContextWrapper(httpContext);
var routeData = new RouteData();
var requestContext = new RequestContext(httpContextBase, routeData);

return new UrlHelper(requestContext);

Він містить URL мого сайту. Там я її зняв.
pupeno

4
Враховуючи, що клас UrlHelper покладається на контекст запиту (і контекст HTTP), побудова цих контекстних об'єктів може вручну дати неочікувані результати. Якщо HttpContext.Current є нульовим, і ви використовуєте такий підхід, я ставлюся обережно.
Шон

4
Остерігайтеся цієї відповіді - маневровий RequestContext призводить до отримання UrlHelper, який завжди повертає порожню рядок.
gknicker

47

UrlHelper може бути побудований з дії Controller із наступним:

 var url = new UrlHelper(this.ControllerContext.RequestContext);
 url.Action(...);

Поза контролером, UrlHelper може бути побудований шляхом створення RequestContext з RouteTable.Routes RouteData.

HttpContextWrapper httpContextWrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
UrlHelper urlHelper = new UrlHelper(new RequestContext(httpContextWrapper, RouteTable.Routes.GetRouteData(httpContextWrapper)));

(На основі відповіді Брайана, додано незначну корекцію коду.)


2
Але у мене немає контролера в моделі.
pupeno

Гаразд, вибачте, я не знав, де саме виконується код. Дозвольте мені поглянути ...
Натан Тейлор

2
Не потрібно створювати новий контекст запиту:var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
bradlis7,

Приємно @ bradlis7 Це MVC 5?
Натан Тейлор

1
Не працює, тому що this.ControllerContext.RequestContextє HttpRequestContextконструктором і UrlHelperочікує, що "a" RequestContext. Обидва класи не пов'язані між собою.
Флоріан Зима

8

Так, ви можете це створити. Ви можете зробити щось на кшталт:

var ctx = new HttpContextWrapper(HttpContext.Current);
UrlHelper helper = new UrlHelper(
   new RequestContext(ctx,
   RouteTable.Routes.GetRouteData(ctx));

RouteTable.Routesє статичною властивістю, тож вам повинно бути в порядку; щоб отримати HttpContextBaseдовідку, HttpContextWrapperпосилається на це HttpContextі HttpContextдоставляє це.


Це не вийде, хоча це дуже близько. Дивіться мою відповідь нижче.
Натан Тейлор


0

Я намагався зробити щось подібне всередині сторінки (поза контролером).

UrlHelper не дозволив мені сконструювати це так просто, як відповів Паблос, але тоді я згадав старий трюк, щоб ефективно робити те саме:

string ResolveUrl(string pathWithTilde)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.