0

I have VisualStudio 2017. I am working on a simple app. I look up a username and return some information on that person. The oddity this time is that due to where this app will live in the corporate structure the url will be something like:

https://specialAps.my.company.com/MyUserLookup

I can do a WebDeply and based on that configuration the index page appears as I expect at the URL above (note: there is no trailing "/").

The index page is a very simple form with one text input box for the username and a submit button. a jQuery on click event handler catches the submit event and calls the "Search" action in the "Home" controller.

    $.ajax({
        url: "/Home/UserSearchResult",
        dataType: "json",
        traditional: true,
        data: {
            username: $("#UserSearchForm input#username").val().trim()
        }
    }).done(...
    ).fail(...);

This builds a request to:

https://specialAps.my.company.com/Home/UserSearchResult?username=auser

which is invalid because the App Name is no longer in the URL.

I changed the ajax call to:

    $.ajax({
        url: "/MyUserLookup/Home/UserSearchResult",
        dataType: "json",
        traditional: true,
        data: {
            username: $("#UserSearchForm input#username").val().trim()
        }
    }).done(...
    ).fail(...);

which seems like it should be the right address but Chrome DeveloperTools reports that the request gets canceled, no request preview or result. If I run the request by hand in a different browser window I get a 400 level "Bad Request" result.

Is this a RouteConfig issue? I currently have the default route:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.LowercaseUrls = true;

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }

I have tried adding the App Name into the route url:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.LowercaseUrls = true;

        routes.MapRoute(
            name: "Default",
            url: "MyUserLookup/{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }

but then I get 403 Forbidden results on trying to reach the index page.

All of my other projects have had URLs of the form: "https://AppName.host.name" or "https://AppName.host.name/Home/...", what am I missing here?

EDIT

The Admins swear the server is configured correctly.

The jQuery ajax code above is in its own file and is included in the index.cshtml file via a bundle. I have tried setting the url: value in the ajax call to:

    url: "@Url.Action('UserSearchResult', 'Home')"

but that just urlencods and embeds @Url.Action('NetidSearchResult', 'Home') in the generated url.

Now I have added a hidden text field to the simple form and set its value to that of the @Url.Action(...). I then use that value in the ajax call as:

    url: $("#UserSearchForm input#url").val().trim()

On my desktop (localhost) this generates the correct looking url:

http://localhost:5784/home/usersearchresult?username=auser

but that request gets canceled for some unknown reason. Chrome DeveloperTools reports under the network tab:

usersearchresult?netid=auser    (canceled)  xhr jquery-3.3.1.js:9600    0 B 27 ms

If I put breakpoints in the UserSearchResult method I can see that the method runs to completion. The response object claims a 200 level status. If I paste the full url into the browser then I get back the JSON object I expect.

The outline of the search method is below. I can examine the personSearchResult Dictionary and know it has stuff in it.

    [HttpGet]
    public ActionResult UserSearchResult(string username) {
        var myUser = username.Trim().ToLower();

        var personSearchResult = new Dictionary<string, object> {
            ["errors"] = new List<string>()
        };

        try {
            ... put stuff in personSearchResult ...
        } catch (Exception e) {
            Response.StatusCode = 400;
            ((List<string>) personSearchResult["errors"]).Add(e.Message);
        }

        return Json(personSearchResult, JsonRequestBehavior.AllowGet);
    }

I have also replaced the return of the possibly complex personSearchResult object with a trivial Json string and all this still happens.

EDIT 2

I have discoverd that since I am activating the ajax call from an onsubmit handler that I have to return false;. That's not the whole answer but its progress.

EDIT 3

Well, that was certainly deeply buried. Turns out that the "service account" that the web server was using to run this app instance did not have permissions to access databases and other resources. That was not being reported in any useful way. Above, I was catching the exception message and putting it in a Dict that would become a Json object in the response... except it didn't. I just set

    Response.StatusDescription = e.Message;

in the catch and saw the error.

7 Reeds
  • 2,419
  • 3
  • 32
  • 64
  • 1
    You say `https://specialAps.my.company.com/Home/UserSearchResult?username=auser` is invalid, but `http://localhost:5784/home/usersearchresult?username=auser` (the same route) is valid. Therefore, your question is unclear - what is a **valid URL** as opposed to an invalid one? You say that the `appName` is in the query string, but I see a user name there. Please clarify what you are trying to achieve. – NightOwl888 Feb 13 '18 at 04:33
  • 1
    Do note that the default routing classes ***completely ignore*** host name and query string. The only thing they consider is the path unless you [customize routing](https://stackoverflow.com/a/48602769/) to consider other parts. – NightOwl888 Feb 13 '18 at 04:38
  • @NightOwl888: You are completely correct about my question being unclear wrt the urls. On localhost the query path is just 'controller/action'. On the dev server the admins configured this app to have its appName as the first element of the query path: .../myApp/controller/action'. When I wrote those lines some aspect of my code was not adding the appName into the target url as it should have. – 7 Reeds Feb 13 '18 at 15:31

1 Answers1

0

Are you able to access your application from your local machine?

Default route config is fine as you mentioned.

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.LowercaseUrls = true;

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }

No need to include hostname/virtual directory name in the route configuration.

I think IIS server is not configured properly and the request is not reaching your application. I recommend checking IIS configuration for this issue.

SMR
  • 136
  • 5