MVC 5 - URL.Action Route Bind Issue - ajax

I'm using PagedList.Mvc to create Ajax pagination of my data. However I'm having a problem with an URL.Action that is added to a data-href attribute, after the partial view has been return.
When the page loads for the first time this issue doesn't occur, it's only after I have made an ajax request using the pagination results that url.action doesn't seem to bind correctly.
This is the action that the URL.Action should link to (note the 'Route' Attribute):
[Route("Project/{code}/Request/{number}")]
public ActionResult Details(string code, int number)
{
if (number == 0 || code == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var viewModel = _requestLogic.GetIrDetailsViewModel(code, number);
if (viewModel == null) return HttpNotFound();
return View(viewModel);
}
On the main view I add an Html.Action to this Action:
[HttpGet]
public PartialViewResult GetProjectRequests(string code, int page = 1, int pageSize = 10)
{
var viewModel = _requestLogic.GetRequestsForProject(code, page, pageSize);
return PartialView("_ProjectRequestsList", viewModel);
}
This Action is also used by the ajax call for the tables pagination, hence the page and pageSize arguments.
Inside this partial view I render a table with the model data, adding the data-href attribute to each row like so:
#foreach (var item in Model)
{
<tr class='clickable-row' data-href='#Url.Action("Details", new {number = item.RequestNo})'>
<td>....
}
This will render the data-href attribute like so:
However after I make a successful ajax call and the html for the partial is replaced. This attribute values doesn't resolve in the same way.
It ends up like this:
Any idea why this is happening?
I bind a double click attribute to any row with the class .clickable-row which is what makes use of this data-href attribute. Hence why I need this to work.
Cheers,

Thanks to #RosdiKasmin I have solved the problem. I have added a route attribute to the partial view action that is used on the initial page load and via the ajax call. Like so:
[HttpGet]
[Route("Project/{code}/")] // <- I've added this.
public PartialViewResult GetProjectRequests(string code, int page = 1, int pageSize = 10)
{
var viewModel = _requestLogic.GetRequestsForProject(code, page, pageSize);
return PartialView("_ProjectRequestsList", viewModel);
}
// GET: Requests/Details/5
[Route("Project/{code}/Request/{number}")]
public ActionResult Details(string code, int number)
{
if (number == 0 || code == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var viewModel = _requestLogic.GetIrDetailsViewModel(code, number);
if (viewModel == null) return HttpNotFound();
return View(viewModel);
}
This means that the Url.Action makes use of the existing URL when creating the action link.

Related

MVC CORE [HttpPost] method not being called by View

I have this link in a View page:
#{
var link = Url.RouteUrl("newOrgNodes", new { controller = "Nodes", Action = "PostBundleNodes", n_qty = 2, org_id = 20 });
Create Nodes
}
In Program.cs I have the following custom route mapping:
app.MapControllerRoute(name: "newOrgNodes",
pattern: "Nodes/PostBundleNodes/{n_qty}/{org_id}",
defaults: new { controller = "Nodes", action = "PostBundleNodes" } );
My Controller has 2 [HttpPost] methods, one of which is:
[HttpPost(), ActionName("PostBundleNodes")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> PostBundleNodes(NodeWriteViewModel newnodes, int n_qty, int org_id)
{
// code here
}
When I hover over the button in the View (parameters hard coded for now) the URL is what I expected it to be but when I click on the button, it loads a blank page instead of hitting the breakpoint in the PostBundleNodes Post method. I thought using [ActionName] in the controller would suffice but no. What am I doing wrong?

Post selected dropdown to controller MVC using AJAX or other way

I need to post the selected item's id from dropdown to post method of same controller and the render the content in same view
PLease help me fast :(
My View
#Html.DropDownListFor(x => x.hotelmodel.SelectedHotelId, Model.hotelmodel.DrpHotelList)
<div>
<p>#Model.percentageoccupied</p>
<p>#Model.Revenue</p>
<p>#Model.UnSold</p>
<div>
MY HttpGetMethod
[HttpGet]
public ActionResult Counter()
{
var personid = ((PersonModel)Session["PersonSession"]).PersonId;
var model = new CounterforModel();
model.hotelmodel.DrpHotelList = iCommonservice.GetHotelListByPersonId(personid);
return View(model);
}
My HttpPostMethod
[HttpPost]
public ActionResult Counter(int id)
{
var result = iCommonservice.LoadCounter(id);
model.percentageoccupied = Convert.ToInt32(result[0].percentageoccupied);
model.Revenue = Convert.ToDecimal(result[0].Revenue);
model.UnSold = Convert.ToInt32(result[0].UnSold);
return View(model);
}
In your POST method pass your View Model as parameter. Then you can use the posted hotelModel.SelectedHotelId for what you need, update the model values and pass your updated model to the View.
public ActionResult Counter(CounterforModel model)
{
var result = iCommonservice.LoadCounter(model.hotelmodel.SelectedHotelId);
model.percentageoccupied = Convert.ToInt32(result[0].percentageoccupied);
model.Revenue = Convert.ToDecimal(result[0].Revenue);
model.UnSold = Convert.ToInt32(result[0].UnSold);
return View(model);
}
If you want, you can use #Ajax.BeginForm() or jQuery .ajax() to make an ajax call to your action. You can look here.

MVC 3 How to tell what view a controller action is being called from-

Is there a way to tell what view a controller action is being called from?
For example, I would like to use "ControllerContext.HttpContext.Request.PhysicalPath" but it returns the path in which the controller action itself is located:
public ActionResult HandleCreateCustomer()
{
// Set up the customer
//..code here to setup the customer
//Check to see of the calling view is the BillingShipping view
if(ControllerContext.HttpContext.Request.PhysicalPath.Equals("~/Order/BillingShipping"))
{
//
return RedirectToAction("OrderReview", "Order", new { id = customerId });
}
else
{
return RedirectToAction("Index", "Home", new { id = customerId });
}
}
If you have a fixed number of locations that it could possibly be called from, you could create an enum where each of the values would correspond to a place where it could have been called from. You'd then just need to pass this enum value into HandleCreateCustomer, and do your condition statement(s) based on that.
At the moment I am using something of the sort:
In the View I am populating a TempData variable using:
#{TempData["ViewPath"] = #Html.ViewVirtualPath()}
The HtmlHelper method ViewVirtualPath() is found in the System.Web.Mvc.Html namespace (as usual) and is as follows and returns a string representing the View's virtual path:
public static string ViewVirtualPath(this HtmlHelper htmlHelper)
{
try{
return ((System.Web.WebPages.WebPageBase)(htmlHelper.ViewDataContainer)).VirtualPath;
}catch(Exception){
return "";
}
}
I will then obviously read the TempData variable in the controller.
I found another way.
In the controller you want to know what page it was called from.
I added the following in my controller
ViewBag.ReturnUrl = Request.UrlReferrer.AbsolutePath;
Then in the View I have a 'Back' button
#(Html.Kendo().Button().Name("ReturnButton")
.Content("Back to List").Events(e => e.Click("onReturn"))
.HtmlAttributes(new { type = "k-button" })
)
Then the javascript for the onReturn handler
function onReturn(e) {
var url = '#(ViewBag.ReturnUrl)';
window.location.href = url;
}

assigning variables in the View in ASP MVC 3

Actually I'm very new to ASP.NET MVC and I need your help.
Here I have some Create Method that takes an argument from the URL to use it as id:
in 'vote' controller :
public ActionResult Create(int id)
{
Meeting meeting = db.Meetings.Find(id); // get the object
ViewBag.meetingID = meeting.meetingID; // get its id and assign it to a ViewBag
return View();
}
and I would like to do something like :
vote.meetingID = #ViewBag.meetingID
in the model so that is directly assgin this property without excplicitely typing it from the HTML view (I mean #Html.EditorFor(model=>meetingID) )
The question is not that clear, but try this.
You could pass the entire model to the view.
Controller:
public ActionResult Create(int id)
{
Meeting meeting = db.Meetings.Find(id); // get the object
ViewData["myMeeting"] = meeting;
return View();
}
To use in the view you can declare it as a variable at the top of the view:
Declare:
#
{
var meetingData = ViewData["myMeeting"] as Meeting;
}
Usage:
<div>
#meetingData.meetingID
</div>

ASP MVC Edit Post Function has null Parameter

I'm trying to create a very basic MVC app based on a tutorial. I am using the default routing, and simple Views and Model.
The problem I am having is with the HttpPost Edit function. I am expecting an object of my "MyObject" type to be passed as the parameter, but it always comes back null.
Here are my Edit functions from the controller (the Get function works properly):
public ActionResult Edit(int? id)
{
if (!id.HasValue)
return RedirectToAction("Index");
var item = (from obj in mDB.MyDatabaseObjects
where obj.Id == id
select obj).First();
return View(item);
}
//
// POST: /Main/Edit/5
[HttpPost]
public ActionResult Edit(MyDatabaseObject someObject)
{
var original = (from obj in mDB.MyDatabaseObjects
where obj.Id == someObject.Id
select obj).First();
if (!ModelState.IsValid)
return View(original);
mDB.ApplyCurrentValues(original.EntityKey.EntitySetName, someObject);
mDB.SaveChanges();
return RedirectToAction("Index");
}
Note that my (nearly identical) Create method works as expected:
[HttpPost]
public ActionResult Create([Bind(Exclude="Id")] MyDatabaseObject newObject)
{
if (!ModelState.IsValid)
return View();
int max = mDB.MyDatabaseObjects.Max(data => data.TaskOrder);
newObject.TaskOrder = max + 1;
mDB.AddToMyDatabaseObjects(newObject);
mDB.SaveChanges();
return RedirectToAction("Index");
}
Thanks,
wTs
Ensure the values on your view for MyDatabaseObject are inside of the form. Validate these values are being posted over - inspect Request.Form or use change the method signature to use
FormsCollection collection
simply to validate the values are getting posted. If its choosing that method - it should be matching the properties to the form field - its generally very simple.

Resources