user1608132
user1608132

Reputation: 301

ASP.net MVC Controller will not return view

Still kinda new to ASP.net and I have this strange problem. Its a very basic scenario but something is up and I can't figure it out. Deploy should return a view named Deploy that is typed to the model CompiledAppModel. However, when you click install in the view it never leaves the page despite calling the return View() method. Any ideas?

Here is my controller:

[HttpPost]
public ActionResult Deploy(string key_name, string custom_folder = "")
{
    string userId = Membership.GetUser().ProviderUserKey.ToString();
    UserDataModel user_info = _user_data_service.getUserDataByPrimaryIDNoDB(userId, HttpContext.Cache);
    log.Trace("Deploy was called. key_name:" + key_name + " UID: " + user_info.UID);

    // first we'll call the info to install remote application
    bool serviceInstall = _fms_app_service.DeployFmsApp(user_info, key_name, custom_folder);

    // then we'll call to generate client side info
    bool clientInstall = _fms_app_service.CompileClientApp(user_info, key_name);

    var model = _fms_app_service.getInstalledAppInfo(user_info, key_name);
    if (serviceInstall && clientInstall)
    {
        return RedirectToAction("Deploy", model);
    }

    return View("Error");
}

and my view:

@model IEnumerable<Models.Applications.FmsAppModel>

@foreach (var item in Model) {
    <div class="col">
        <h2>@Html.DisplayFor(modelItem => item.friendly_name)</h2>
        <p>@Html.DisplayFor(modelItem => item.app_description)</p>
        <p><strong>Tags:</strong> @Html.DisplayFor(modelItem => item.app_type)</p>

        <a href="#" class="btn btn-primary install-app" data-key-name="@(item.key_name)">Install</a>

        @Html.ActionLink("Details", "Detailss", new {  id=item.app_id  })
    </div>
}
</div>

<script type="text/javascript">
   (function () {
        $('.install-app').on('click', function (e) {
            e.preventDefault();
            var data_key_name = $(this).data('key-name');
            //ajax install app
            $.ajax({
                type: "POST",
                url: '@Url.Action("Deploy")',
                data: {
                    key_name: data_key_name
                }
            });
        });
    })();
</script>

And the model.

public class CompiledAppModel
{
    [Display(Name = "Admin URL")]
    public string adminURL { get; set; }

    [Display(Name = "Viewer URL")]
    public string viewerURL { get; set; }

    [Display(Name = "Embed URL")]
    public string embedURL { get; set; }
}

Upvotes: 8

Views: 7116

Answers (3)

b_meyer
b_meyer

Reputation: 604

I assume that you really want to redirect after making the ajax call.

As far as i know, you have to implement a custom ActionResult, something like:

public class AjaxAwareRedirectResult : RedirectResult
{       
    public AjaxAwareRedirectResult(String url)
        : base(url)
    {
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if ( context.RequestContext.HttpContext.Request.IsAjaxRequest() )
        {
            String destinationUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext);

            JavaScriptResult result = new JavaScriptResult()
            {
                Script = "window.location='" + destinationUrl + "';"
            };
            result.ExecuteResult(context);
        }
        else
        {
            base.ExecuteResult(context);
        }
    }
}

In your controller, just do:

    [HttpPost]
public ActionResult Deploy(string key_name, string custom_folder = "")
{
    string userId = Membership.GetUser().ProviderUserKey.ToString();
    UserDataModel user_info = _user_data_service.getUserDataByPrimaryIDNoDB(userId, HttpContext.Cache);
    log.Trace("Deploy was called. key_name:" + key_name + " UID: " + user_info.UID);
    // first we'll call the info to install remote application
    bool serviceInstall = _fms_app_service.DeployFmsApp(user_info, key_name, custom_folder);
    // then we'll call to generate client side info
    bool clientInstall = _fms_app_service.CompileClientApp(user_info, key_name);

    var model = _fms_app_service.getInstalledAppInfo(user_info, key_name);
    if (serviceInstall && clientInstall)
    {
        return RedirectToAction("Deploy", model);
    }
    return AjaxAwareRedirectResult("/foo");
}

But, as I said, this is just me assuming that you really want to redirect after the ajax call.

Upvotes: 5

Pablo Romeo
Pablo Romeo

Reputation: 11396

Doing an HTTP redirect after an ajax call might not make a whole lot of sense. You could do that simply with an html form and a regular POST.

However, if you really need redirection and still want the POST through AJAX you could do it by returning Json instead of a redirect, as suggested in the following answers:

In that case, you could return the target action url within a Json object, and use that info in your success handler as shown in Neil's answer.

Also, remember that RedirectToAction is just a 302 redirect, therefore, it won't render a view directly so you wouldn't pass it a full-blown ViewModel, just the Action Url for the browser to issue the GET to.

That target GET action should be the one responsible for obtaining your Installed App Info and passing that as parameter to a view, following the POST-REDIRECT-GET pattern.

Upvotes: 1

Neil F
Neil F

Reputation: 402

Looks to me like your using an Ajax call to do your post back to the server, in which case the result isn't going to get rendered to the page without a little extra work. You can define a success handler on the ajax call to take action when the ajax call returns. So something like

<script type="text/javascript"> (function () {
    $('.install-app').on('click', function (e) {
        e.preventDefault();
        var data_key_name = $(this).data('key-name');
        //ajax install app
        $.ajax({
            type: "POST",
            url: '@Url.Action("Deploy")',
            data: {
                key_name: data_key_name
            },
            success: function(data) { alert(data) }
        });
    });
})();

will give you an alert message with the HTML returned from the ajax call when the request completes.

I'd also use Firebug or the developer tools in Chrome to view the HTML returned, if there is an exception occurring on the server you should be able to inspect this in more detail using these tools.

Upvotes: 1

Related Questions