MVC3 Routing problem HTTP 404 - asp.net-mvc-3

I'm at a loss trying to figure out why I have Actions that are returning 404 'The Resource cannot be found' errors.
Controller Name: ItemManagementController
My Index view has list of items in a table. Each row contains two links, 'Delete' and 'Request Update'. The Delete link calls a Delete action and works fine. The Request Update gives me the 404 error, and seems as if trying to navigate to a URL like http://localhost/TVAPDev/ItemManagement/RequestUpdate?itemID=9.
I have to assume I'm missing something simple, as they are identical in what they do from the view aspect. The actions as defined in the controller are both similar except that they call different methods on a service layer, but that's it.
Here are my two Controller Actions.
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult Delete(int itemID) {
var svc = new ItemManagementService(_repository);
var requestModel = svc.GetItemDeleteModel(itemID);
svc.DeleteItem(requestModel);
var message = requestModel.ActionMessage;
return Json(new { id = itemID, ChangeStatus = requestModel.ItemDetails.ItemChangeStatus.ToString(), ChangeType = requestModel.ItemDetails.ItemChangeType.ToString(), message});
}
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult RequestUpdate(int itemID) {
var svc = new ItemManagementService(_repository);
var requestModel = svc.GetItemUpdateRequestModel(itemID);
svc.RequestItemUpdate(requestModel);
var message = requestModel.ActionMessage;
return Json(new { id = itemID, ChangeStatus = requestModel.ItemDetails.ItemChangeStatus.ToString(), ChangeType = requestModel.ItemDetails.ItemChangeType.ToString(), message });
}
Here are the links as they are defined in the View
<td class="tblist" style="white-space: nowrap;">
#Html.ActionLink("Request Update", "RequestUpdate", new { itemID = item.ItemID }, new AjaxOptions {
HttpMethod = "POST",
Confirm = "Request an Update to this item?",
OnSuccess = "actionCompleted"
})break;
}
</td>
<td class="tblist" style="white-space: nowrap;">
#Ajax.ActionLink("Delete", "Delete", new { itemID = item.ItemID }, new AjaxOptions {
HttpMethod = "POST",
Confirm = "Are you sure you want to delete this Item?",
OnSuccess = "actionCompleted"
})
</td>
Again, the Delete here works without issue. The Request Update link gives me the Http 404 error.
Anyhelp here would be greatly appreciated.

Why are you using AjaxOptions on a normal Html.ActionLink (which is what Request Update is)?
Maybe you wanted it to be like this:
#Ajax.ActionLink(
"Request Update",
"RequestUpdate",
new {
itemID = item.ItemID
},
new AjaxOptions {
HttpMethod = "POST",
Confirm = "Request an Update to this item?",
OnSuccess = "actionCompleted"
}
)

Check your View code... the delete is using the Ajax html helper and the update is using the regular html helper.

Related

Redirect to partial view on another controller

I am new in asp.net mvc programming, please be gentle... :)
Please notice that the following views are all PARTIAL views! Methods are called through Ajax and redirect to partial views with lists, forms are posted through Ajax, etc. OK, here we go...
1st controller named AlertsController. One of the methods is ResolveAlert(Guid id) which returns RedirectToAction -> UnresolvedAlerts() which is just a list of unresolved alerts.
2nd contoller named FrontDeskController. One of the methods is CustomerDetails(Guid id) which lists the customer and alerts that he might have.
I want to be able to "Resolve an alert" (thus use the method of the 1st controller) but return to the page that I was before instead of going to the redirected page that the method returns.
I added a second parameter to the ResolveAlert() method which lists a returnUrl string. I manage to send the Url that I want it to redirect to but I get just the partial (not rendered inside the whole page as it should)...
Here's my ResolveAlert method on my AlertsController:
// Resolve Alert POST
[HttpPost]
public async Task<ActionResult> Resolve(AlertModel model, string redirectUrl)
{
await _AlertsService.ResolveAsync(model);
if (!string.IsNullOrWhiteSpace(redirectUrl))
return Redirect(redirectUrl);
return RedirectToAction("Unresolved");
}
...and here is my CustomerDetails() method on my FrontDeskController:
// Display Customer Alerts
public async Task<PartialViewResult> CustomerDetails(AttendanceModel model, Guid id)
{
var customer = await _CustomersService.ReadAsync(id);
ViewData["Customer"] = await _CustomersService.ReadCustomerExtendedAsync(id);
var alerts = await _AlertsService.ReadCustomerAlertsAsync(id);
ViewData["Alerts"] = alerts.Where(x => x.IsResolved == false).ToList();
return PartialView("_CustomerDetails", model);
}
The ResolveAlert() method of the first controller is called in two steps... 1st I call a modal from the CustomerDetails view:
function resolveAlert(alertId, customerId) {
var returnTo = '/FrontDesk/CustomerDetails/' + customerId;
$.ajax({
method: 'GET',
url: '/Alerts/Resolve/' + alertId,
data: {returnUrl : returnTo},
dataType: 'html'
}).then(function (html) {
$('#dialog-container').html(html);
showDialog();
});
}
...then on the modal I have:
#{
var data = Request.Params["returnUrl"];
}
#using (Ajax.BeginForm("Resolve", "Alerts", new { redirectUrl = data}, new AjaxOptions() { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "partial", OnSuccess = "hideDialog" }, new { id = "form", #class = "form-horizontal" }))
{ ..... textbox with some notes that I can post while resolving the alert ..... }
... and (finally) here is the final part at the bottom of my modal:
<script type="text/javascript">
$('#form').validate({
rules: {
AlertNotes: {
required: true
}
},
submitHandler: function (form) {
$.ajax({
url: $(form).attr("action"),
data: $(form).serialize(),
type: $(form).attr("method")
}).then(function (result) {
$("#partial").html(result);
hideDialog();
});
}
});
</script>
I think that in order for the returned partial to get rendered correctly inside its container I should be returning a RedirectToAction from the ResolveAlert() method but the problem is that it belongs on a different controller...
Is it possible to get this working somehow or should I just bite the bullet and forget about having those pages as partials, get rid of the Ajax calls and use normal Url.Action() links?
It was just a Javascript/Ajax bug in my code.... Please disregard the question...
For those wondering, I had 2 forms using the same id. JS died silently allowing the form to be posted normally and not through Ajax. It had me scratching my head for a while now. Too bad that web development tools and VS in particular can't snipe such errors and provide a meaningful hint to assist you in debugging...

How to get full AJAX URL request after Ajax.BeginForm complete?

In my code, when user presses the submit button, it will execute an AJAX request to the controller.
It's all doing fine, however, I also wanted to update the browser URL to include the full query string (e.g. http://localhost/Forecast?BillingToes=123&Year=2016).
The Controller is returning a partial view with a model. Adding an additional property containing the full URL with query string seems to be OK. However, it seems pretty awkward.
So my question is, is there a way to retrieve the full URL via JavaScript after OnComplete? Below is my View:
#using (Ajax.BeginForm("UpdateForecast", null, new AjaxOptions
{
HttpMethod = "Post",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "forecastControlPart",
LoadingElementId = "ajaxSpinnerImage",
OnBegin = "DeactivateForm",
OnSuccess = "initAppendHeader();UpdateURL(xhr)",
OnComplete = "ReloadFiltersBehaviour"
}, new
{
#class = "onChangeForm",
data_currencyurl = #Url.Action("GetCurrencyForBilling", "DataSource"),
}))
I found the solution to my problem, using $(form).serialize() can fetch all the parameters the form submit to the server, so my code would look like:
In my View:
#using (Ajax.BeginForm("UpdateForecast", null, new AjaxOptions {
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
OnSuccess = "initAppendHeader(),UpdateURL(this)",
}))
In my Javascript file:
function UpdateURL(form) {
// Auto-Update browser URL to include parameters after submit.
var formData = $(form).serialize();
window.history.pushState(null, null, formData);
}

Pass selected item ID into partial view

I am building a page where a user can view the details of an item which s/he selected.
As part of this project, I need to show all the comments that are listed under this particular item using Ajax and partial views.
In the Controller class, I am somehow unable to pass the productID of the selected item to the partial view method. When I hard code the productID into the method, the comments show up, however when I pass it through the parameter, the method won't even trigger.
All the product details, however, show without restrictions.
I would appreciate any help. Below please find the code in my Controller
public ActionResult Index()
{
List<Product> productList = new ProductClient().GetAllProducts().ToList();
return View("Index", productList);
}
//This method works correctly. The id of the product is passed.
public ActionResult Details(int id)
{
return View(new ProductClient().GetProductByID(id));
}
// This method is not even getting triggered.
public PartialViewResult ProductComments(int id)
{
List<Comment> commentList = new ProductCommentClient().GetCommentsByProductID(id).ToList();
return PartialView("_comments", commentList);
}
This is my Details.cshtml
#Ajax.ActionLink("Product Comments", "ProductComments(" + #Model.ID + ")", new AjaxOptions
{
HttpMethod = "Get",
UpdateTargetId= "divComments",
InsertionMode = InsertionMode.InsertAfter
})
<fieldset>
<div id="divComments">
<legend>Comments</legend>
</div>
</fieldset>
Many thanks in advance.
I solved this.
#Ajax.ActionLink("Product Comments", "ProductComments", new {id=Model.ID}, new AjaxOptions
{
HttpMethod = "Get",
UpdateTargetId= "divComments",
InsertionMode = InsertionMode.InsertAfter
})
<fieldset>
<div id="divComments">
<legend>Comments</legend>
</div>
</fieldset>
I was passing the ID in the wrong manner. I hope that this would at least help somebody else.

call to controller to populate text box based on dropdownlistfor selection using Ajax

I have a dropdown and when I select an item from it, I want to pass on the selected value to a function in a controller, query the db and auto load a text box with query results.
How do I use Ajax to make that call to the controller when there is onclick() event on the dropdown?
My dropdown and textbox in my aspx page is:
<%: Html.DropDownListFor(model => model.ApplicationSegmentGuid, Model.ApplicationSegment)%>
<%: Html.TextAreaFor(model => model.EmailsSentTo, false, new { style = "width:500px; height:50px;" })%>
My function in controller is
public ActionResult AsyncFocalPoint(Nullable<Guid> ApplicationSegmentGuid)
{
string tempEmail = UnityHelper.Resolve<IUserDirectory>().EmailOf();
tempEmail = "subbulakshmi.kailasam#lyondellbasell.com" + tempEmail;
IList<string> EmailAddresses = new List<String>();
using (TSADRequestEntities context = UnityHelper.Resolve<TSADRequestEntities>())
{
EmailAddresses = context.FOCALPOINTs.Where(T => T.APPLICATIONSEGMENT.ItemGuid == ApplicationSegmentGuid && T.FlagActive)
.Select(T => T.Email).ToList();
}
foreach (string emailAddress in EmailAddresses)
tempEmail = tempEmail + ";" + emailAddress;
return Json(tempEmail, JsonRequestBehavior.AllowGet);
}
You could give your dropdown an id and url:
<%= Html.DropDownListFor(
model => model.ApplicationSegmentGuid,
Model.ApplicationSegment,
new { id = "myddl", data_url = Url.Action("AsyncFocalPoint") }
) %>
and then subscribe to the .change() event of the dropdown list unobtrusively and trigger the AJAX request:
$(function() {
$('#myddl').change(function() {
// get the selected value of the ddl
var value = $(this).val();
// get the url that the data-url attribute of the ddl
// is pointing to and which will be used to send the AJAX request to
var url = $(this).data('url');
$.ajax({
url: url,
type: 'POST',
data: { applicationSegmentGuid: value },
success: function(result) {
// TODO: do something with the result returned by the server here
// for example if you wanted to show the results in your textarea
// you could do this (it might be a good idea to override the id
// of the textarea as well the same way we did with the ddl):
$('#EmailsSentTo').val(result);
}
});
});
});

ASP.NET MVC 2: prevent ajax action link from replacing the updateTarget

I use an ajax action link on a view, then bind a js function onto its onCompleted property.
In this function, i get the response object, do some funny stuff, then write the message property to the updatetarget element.
The problem is, when it finishes its work on the oncompleted event, it writes the raw json response onto the updatetarget element, replacing the text i already written. I want to prevent it to write the raw response to the updatetarget. I'm aware of the InsertionMode property, but its useless to me because it appends text to the element one way or another.
The scripts i mentioned are below;
The code of the action link on view:
<%: Ajax.ActionLink("Delete", "Delete",
new { id = Model.Id, secretKey = Model.SecretKey },
new AjaxOptions { OnComplete = "WriteJsonResultToElement", UpdateTargetId="commandResult" })
%>
The WriteJsonResultToElement function
function WriteJsonResultToElement(resultObject) {
updateTarget = resultObject.get_updateTarget();
obj = resultObject.get_object();
$(updateTarget).text(obj.message); // here i set the text of update target
if (obj.result > 0)
$('*:contains("' + obj.id + '")').last().parent().remove();
}
My JsonResult Delete method returns this data after action:
{"message":"Deleted","result":1,"id":132}
Thanks.
If you don't want the raw JSON response appended to the DOM don't specify an UpdateTargetId:
<%: Ajax.ActionLink(
"Delete",
"Delete",
new { id = Model.Id, secretKey = Model.SecretKey },
new AjaxOptions { OnComplete = "success" })
%>
and handle it in the success callback:
function success(result) {
var obj = result.get_object();
alert(obj.message);
// TODO: do something with the object
}

Resources