Reputation: 301
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
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
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
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