MVC 3 Url Helper Giving Incorrect URL
Asked Answered
S

2

3

I am developing a MVC 3 application for a corporate intranet site and I am having some issues with the URL helper sometimes not producing correct URLs. The application is being accessed through an access manager application that is controlled by our IT department which basically provides a standardized URL so that the user does not need to know any information about the server. For example, to access the application directly on the server, I would visit:

http://philsserver/App

Through the access manager, I would use the URL provided by the IT department:

http://secureintranet/PHILSAPP/App/

I am using the MVC URL helper in several places in my application - the issue is that sometimes the "PHILSAPP" part is left out - when I use it within an "<a>" link, it works, but when I use it in elsewhere, it does not.

For example, the code:

<a href="@Url.Action("Index", "FormsAndTemplates")">

correctly creates the link as:

<a href="/PHILSAPP/App/FormsAndTemplates">.

The following code:

@Html.TextBox("lastName", ViewBag.LastName as string, new { @class = "input-mini", @autocomplete = Url.Action("QuickSearch", "Employee") })

produces:

<input autocomplete="/App/Employee/QuickSearch" class="input-mini" id="lastName" name="lastName" type="text" value="" />

Notice that this URL does not contain the "PHILSAPP" part. This also happens if I use the URL helper in javascript or just about anywhere other than an "<a>" tag. Does anyone have any idea why this would be happening? As far as I can tell, both calls to Url.Action are pretty much the same so I cannot figure out why this is happening. I apologize if this question has already been answered but I was not able to find any information about someone having a similar problem. Thanks in advance for any assistance.

Update: As requested, my routes are below:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional });

Update 2: The access manager being used is Tivoli Identity Manager if that gives anyone any clues.

Stun answered 3/1, 2013 at 20:1 Comment(3)
Could you post you routes?Fresno
I don't familiar with this Tivoli Identity Manager but reverse proxies in general are usually alter the generated HTML before sending it to the client browser. This alternation of the HTML can affect urls, css, and also the java-scripts. So my guess is the following: the Url.Action always generate the correct url. But inside a href your reverse proxy modifies it. But it does not correctly detects the url inside the autocomplete attribute and leave it unchanged. So I should suggests to contact your IT to inform about your reverse proxy configuration.Tails
@Tails - You are 100% correct, I don't know why that did not occur to me. I am still not sure what my solution will be, but you definitely helped me understand the problem. I checked this by changing one of my <a href="..."> to <a hreff="..."> (notice the extra 'f') - sure enough, the URL was not correctly generated. To make matters worse, if I manually add the "/PHILSAPP" to the URL, the Identity Manager does not recognize it and adds it a second time. Anyway, I am going to continue investigating possible solutions but thanks so much for your help.Stun
S
2

As nemesv pointed out above, the answer was that the Url.Action method was always generating the URL as /App/... but the access manager application would recognize certain tags (such as <a href="/App/...">, <form action="/App/...">, etc.) and would add the /PHILSAPP to the beginning. The solution I am exploring is to write some extension methods for the UrlHelper and HtmlHelper to generate absolute URLs rather than relative URLs where the host name including the /PHILSAPP will be specified in the web.config file. If anyone still has any other suggestions to solve this I would be happy to hear them but otherwise I am satisfied with using this as a work-around.

Some boilerplate code to start with:

namespace MvcApplicationNameSpace
{
    /// <summary>
    /// Extension methods to the UrlHelper class for generating absolute URLs using
    /// Web.config settings
    /// </summary>
    public static class UrlHelperExtensions
    {
        private static string BaseUrl
        {
            get
            {
                return System.Configuration.ConfigurationManager.AppSettings["BaseUrl"];
            }
        }

        /// <summary>
        /// Generates a string for the absolute URL to an action method
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string AbsoluteAction(this UrlHelper url)
        {
            return BaseUrl + url.Action();
        }

        /// <summary>
        /// Generates a string for the absolute URL to an action method with the
        /// specified name
        /// </summary>
        /// <param name="url"></param>
        /// <param name="actionName"></param>
        /// <returns></returns>
        public static string AbsoluteAction(this UrlHelper url, string actionName)
        {
            return BaseUrl + url.Action(actionName);
        }

        /// <summary>
        /// Generates a string for the absolute URL to an action method with the
        /// specified name and route values
        /// </summary>
        /// <param name="url"></param>
        /// <param name="actionName"></param>
        /// <param name="routeValues"></param>
        /// <returns></returns>
        public static string AbsoluteAction(this UrlHelper url, string actionName, object routeValues)
        {
            return BaseUrl + url.Action(actionName, routeValues);
        }

        /// <summary>
        /// Generates a string for the absolute URL to an action method with the
        /// specified name and route values
        /// </summary>
        /// <param name="url"></param>
        /// <param name="actionName"></param>
        /// <param name="routeValues"></param>
        /// <returns></returns>
        public static string AbsoluteAction(this UrlHelper url, string actionName, RouteValueDictionary routeValues)
        {
            return BaseUrl + url.Action(actionName, routeValues);
        }

        /// <summary>
        /// Generates a string for the absolute URL to an action method and
        /// controller
        /// </summary>
        /// <param name="url"></param>
        /// <param name="actionName"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static string AbsoluteAction(this UrlHelper url, string actionName, string controllerName)
        {
            return BaseUrl + url.Action(actionName, controllerName);
        }

        /// <summary>
        /// Generates a string for the absolute URL to an action method and
        /// controller, including route values
        /// </summary>
        /// <param name="url"></param>
        /// <param name="actionName"></param>
        /// <param name="controllerName"></param>
        /// <param name="routeValues"></param>
        /// <returns></returns>
        public static string AbsoluteAction(this UrlHelper url, string actionName, string controllerName, object routeValues)
        {
            return BaseUrl + url.Action(actionName, controllerName, routeValues);
        }

        /// <summary>
        /// Generates a string for the absolute URL to an action method and
        /// controller, including route values
        /// </summary>
        /// <param name="url"></param>
        /// <param name="actionName"></param>
        /// <param name="controllerName"></param>
        /// <param name="routeValues"></param>
        /// <returns></returns>
        public static string AbsoluteAction(this UrlHelper url, string actionName, string controllerName, RouteValueDictionary routeValues)
        {
            return BaseUrl + url.Action(actionName, controllerName, routeValues);
        }
    }
}
Stun answered 4/1, 2013 at 20:44 Comment(0)
I
0

We exactly had the same problem behind our secure entry server. For REST calls, we wanted to generate urls on the server side to make them available in java script. But they didn't include the sub-path added by the secure entry server.

So we came up with a workaround like that (rendered in layout page):

<a id="urlBase" href="/" style="display: none;"></a>
<script type="text/javascript">
    baseUrl = document.getElementById('urlBase').getAttribute('href');
</script>

href="/" has been substitued by the entry server by href="/path/", and we could easily concatenate baseUrl with our relative paths when accessing REST services.

Hope it helps in your case too.

Ingrate answered 4/3, 2014 at 17:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.