MVCContrib grid value is always null when HTML.ActionLink is clicked - asp.net-mvc-3

I'm trying to implement a simple listview / detailview feature in one of our apps. I'm using the MVCContrib Grid (which btw is awesome!) to show the list of items. There's an edit link next to every row on the grid that allows the user to edit the item. When the users click the edit link I execute a Get that returns the details form used to editing the item. For some reason I cannot get the clicked customerId to be sent to the controller. The controller just gets null every time I click the edit link.
My grid is configure like so:
Html.Grid(Model.CheckAccounts)
.Columns(column.For(c => {Html.ActionLink(
"Edit",
"CustomerDetails",
"CustomerManagementController",
new {Id=customer.Id}));
column.For(c => c.Name);
column.For(a => c.AccountNumber);
}).Render();
Here's My controller Action:
[HttpGet]
public ActionResult CustomerDetails(long? Id )
{
//fetch the customer from repo...
//return it to the client
return View(model);
}
I'm totally confused since all the samples and blogs I've seen, access data from the grid the same way I'm doing it. Can someone help?

I hate to answer my own question but I was able to fix this by changing the action link to:
{Html.ActionLink(
"Edit",
"CustomerDetails",
"CustomerManagement",
new {Id=customer.Id}));
I realized the wrong action link was being generated after looking at the "?Length=24" queryString parameter at the end of the URL.
The grid is working as expected now.

Related

kendo drop down list does not autoselect the initial value(--select--)inserted at run time in update method

I am using Kendo grid with pop up editing mode and editor template.
The editor template consists of a kendo drop down list which is bind through the database and i have inserted the optional label value ie "--select--" at run time in controller which works good for add method but for update method it is not autoselecting the "--select value--" and on click value is selected at second hit. Please help if anyone has any solution to this.
Edited: Please find the below code snippet for my drop down list.
#(Html.Kendo().DropDownList().Name("Type")
.DataTextField("Value")
.DataValueField("TypeID")
.DataSource(source =>
{
source.Read(read => { read.Action("Action Name", "Controller name"); });
})
)
// Controller code for binding drop down list
[AllowAnonymous]
public ActionResult GetTypes()
{
//my code to get list of types from db in object "Type"
Type.Insert(0, new TypeModel() { Value = "--Select--", TypeID = Guid.Empty });
return Json(Type, JsonRequestBehavior.AllowGet);
}
As you said in comment section, Kendo UI 2015 Q1 comes with some new features for dropdown family widget e.g autocomplete, dropdown, multiselect, etc and it also has some bug on it.
So its not your fault that the dropdown won't recognize on the first select event.
The developer had fixed this issue and release a service pack for this, therefore all you have to do is upgrade or downgrade your Kendo UI version..
See this dojo where the grid's filter doesn't work for the first time selection
and if you downgrade its version or upgrade it, it will works fine like in this dojo
Kendo UI 2015 Q1 SP1 Release History, you will see on DropDown section that the issue have been fixed..

opening a Popup in mvc3

I have hyperlink column in grid and clicking the link i want to open a popup. Below is my code.
cols.Bound(o => o.PO_NO)
.ClientTemplate(
Html.ActionLink("<#=PO_NO#>",
"SurPODtls",
new { controller = "Home", PO_NO = "<#=PO_NO#>" },
new { target= "_self" }).ToString())
.Title("PO No").Width(30).Filterable(false);
In SurPODtls action method iam returning the partial view of SurPODtls, which contains the telrik window in which iam again calling the partial view to load the controls and data. And same time i have to retain the grid.
But this not works for me. Please provide solution, if anyone have idea
you can use the Custom Column Command here is the link http://demos.telerik.com/aspnet-mvc/grid/customcolumncommand

Alternative for ViewData and QueryString

I have a page(a.aspx) to which im navigating from two different pages(ie there is a link in these two pages where it navigates to a.aspx)
to differentiate from which page i was navigated to a.aspx i used the below code.
passed Querystrings(B1,B2) to the target page as below
Html.ActionLink("test" "Testing", new { Controller = "Stats",prev="B1"},new { #class = "link",target="_self" })
Html.ActionLink("test" "Testing", new { Controller = "Stats",prev="B2"},new { #class = "link",target="_self" })
and in the action of the target page controller i used the below code
ViewData["prev"] = Request.QueryString["prev"].ToString();
and im using this ViewData in the target page ie a.aspx.This is working fine..
Im abit reluctant to use Query.string and ViewData for the above requirement.Please suggest any other alternative approach for the same.
You can use this,
Get the name of the controller
#ViewContext.Controller.ValueProvider.GetValue("controller").RawValue
Get the name of the action
#ViewContext.Controller.ValueProvider.GetValue("action").RawValue
I found that here.
Why not navigate to two separate actions that return the same view? Then, return a model to the view that will indicate the "from" page. You'll know which page you came from by virtue of which action gets hit. It's cleaner, far less complicated, and easier to maintain than trying to pass around this sort of thing in a querystring, viewdata, viewbag, etc. That being said, if you are having to do a lot of this sort of thing, creating separate actions each time around is not reali

How to change WebGrid action for getting data (.NET MVC3)

I have a Partial View that renders WebGrid. My controller looks like
public ActionResult Index()
{
return View();
}
public ActionResult GetUserList(int? page, string sort, string sortdir)
{
var model = UserModel.getList(page,sort,sortdir);
return PartialView("_UserList",model);
}
Index.cshtml :
....
#Html.Action("GetUserList")
The problem is that every time I click on grid navigation or sort links it calls Index method. How can I make Webgrid to execute a different action (GetUserList in this case)? I'm sure I can prepend GetUserList to all links in grid using jquery, but I believe it should be a better way.
It's also possible that what I'm doing is completely wrong, so thanks for your suggestions.
After lot of monkeying around and digging (and even fiddling with Reflector with WebGrid's source code), I came to the conclusion that with WebGrid, you cannot control/change the Header link action.
To create the header link URL, the path is taken from HttpContext.Request.Path, so there is no way to customize it to point to a different route.
One very ugly hack would be to tap into to jQuery Ajax's events (since the header link uses jQuery.load to sort) and overwrite the URL:
Album Id
Better solution would be to use:
Telerik Grid which lets you specify custom routes and also offers much more flexibility in rendering your layout
or MvcContrib Grid (not sure if this lets you modify header links but definitely offers more flexibility than WebGrid)
#MrChief had the idea above about the ugly hack...I put that together. Here is the main code that I used to do this. It does, indeed, hijack the ajax call before it is put on the wire. The key is to modify the URL that is getting sent because the grid will grab that URL from HttpContext.Request.Path. and plug it into the onclick for the anchor element.
I put this into my main common.js and will simply attach a function to capture the ajaxSend event which happens just before the data is sent.
// Used to hijack the sending of all AJAX calls. Before it sends the call to the server, it checks to see if the
// active element (the element that prompted the call) is marked with a given class. If so, then it will perform
// the given operation.
$(document).ajaxSend(function (event, jqXHR, ajaxOptions) {
var activeElement = document.activeElement;
if ($(activeElement).attr('redosorturl') != null) {
// If this is a sort anchor link from a grid that needs to have the sort link redone, do it here.
// the code is in the eipGrip.js file.
if ($(activeElement).attr('redosorturl').toString() == 'redoSortURL') {
var newURL = RedoGridSortURL(activeElement, ajaxOptions.url.toString());
ajaxOptions.url = newURL.toString();
}
}
return false;
});
When rendering the page, I have marked the tag in column header that contains the incorrect URL with a class named "redosorturl', so I know when I hijack the ajax call, the operation has to be done on this element. I then call a custom function that gives me the correct URL, then the ajaxOptions.url is then rewritten with that new URL.
I have to pass the activeElement to that rewrite function so I can traverse up the DOM to get the grid information, where I have put data like the controller and action method that is used along with and IDs and other info that I use for the URL. Likewise, I pass in the current url string because the grid will inject a token at the end of the url that I parse off and put on the new url.
Your conclusion isn't right. You just need to wrap your webgrid in a Get form:
using (Html.BeginForm("GetUserList", "ThingaMaBob", System.Web.Mvc.FormMethod.Get))
{
var grid = new WebGrid(
...
));
Html.Hidden(grid.SortFieldName, grid.SortColumn);
Html.Hidden(grid.SortDirectionFieldName, grid.SortDirection == SortDirection.Ascending ? "ASC" : "DESC");
}
The hiddens are so that the sort dir and sort field end up in parseable form in the querystring. You end up with urls like localhost/ThingaMaBob/GetUserList?someotherfields=whatever=&sort=city&sortdir=ASC
If you remove [HttpPost] attribute and let the route come to the same function. you'll find the Request["page"] value in your method. this will allow you to put a check on Request["Page"] value.

JQuery - which form was submitted?

I have a page of products and for each of them, I want to have a form that uses AJAX to update the session. I've done this bit - just providing background.
I use the product's ID to create a different form class and name for each form, so each form is called something like this_form_name_567 and the next would be this_form_name_568 and so on.
There is a submit button per form. I'm having trouble figuring out
Which event is best to use so that the correct form will be identified when a submit button is clicked?
Once clicked, how to then make sure the correct value is taken from a hidden field (unique ID) within the submitted form so that I can populate a line of code such as:
$.post("compare_response.php", {compare_this: $("#compare_this").val()}, function(data){
}
You can use the .closest tree traversal method to get the form in which the button of interest is nested:
$("input[type=submit]").click(function() {
alert($(this).closest("form").attr("id"));
});
or even simpler, just get the element's form property :)
$("input[type=submit]").click(function() {
alert(this.form.id);
});
You can try it out here.
You can get the form you are submitting like this:
$('form').submit(function() {
var yourForm = $(this);
var hiddenValue = $(this).find('input[type=hidden]').val();
});
Of course you can get the hidden value differently, or if you have more than one hidden you'll have to give a little more information about it.

Resources