MVC WebGrid paging action changing upon navigation - asp.net-mvc

I'm working in an MVC app that is using a webgrid with paging. The grid itself is rendered in a partial view called _Results.cshtml and is rendered in a div on the index.cshtml page using
Html.RenderPartial("_Results", Model.Results);
The partial grid as well as a few other form controls on index.cshtml are wrapped in a form called ResultsAction using:
#using (Ajax.BeginForm("ResultsAction", "Results", new AjaxOptions.....
When intially navigating to the index.cshtml, the grid populates as expected and hovering over any of the paging links correctly display:
http://localhost/ResultsAction?page=<page#>
Each row in the grid has a link to a detail page. This works as expected and the detail page has a link to return to the result grid using:
#Html.ActionLink("Return To Results", "Index", "Results")
Now the problem. This redirects me back to the Index.cshtml just fine but now when I hover over any of the paging links in the grid, they incorrectly are using:
http://localhost/Index?page=<page#>
Which is the wrong controller action so paging no longer functions. My understanding was the paging links should issue a Get using the form name as the action, yet it's being overridden somehow when I navigate to detail then back again. Does anyone know what's causing this behavior or how I can specify the paging links to always use the same controller action?
EDIT: Posting code of partial view as requested:
#model IEnumerable<ispPR_GetInquiryRecords_Result>
#{
Layout = null;
}
<input id="searchListCnt" type="hidden" value="#Model.Count()" />
<div id="gridSearch">
#{
var grid = new WebGrid(selectionFieldName: "SelectedRow", canSort: false, canPage: true, rowsPerPage: 10, ajaxUpdateContainerId: "gridSearch");
var virtualCount = Model != null && Model.Count() > 0 ? Model.First().VirtualCount : 0;
grid.Bind(Model, rowCount: (int)virtualCount, autoSortAndPage: false);
}
<div id="gridContent">
#grid.GetHtml(
htmlAttributes: new { id = "inqgrid" },
tableStyle: "webGrid",
fillEmptyRows: false,
footerStyle: "gridFooter",
displayHeader: true,
alternatingRowStyle: "alt",
selectedRowStyle: "select",
mode: WebGridPagerModes.All,
columns: grid.Columns(
grid.Column("PriceStatus",header:"Price Status"),
grid.Column("CustomerName","Customer Name"),
grid.Column("EndUserName", "End User"),
grid.Column("ContractNumber","Contract"),
grid.Column("PriceLevel", "Level"),
grid.Column("ProductDescription", "Product Code"),
grid.Column(
header: "Break Qty",
format: #<text>#item.QuantityBreak.ToString() / #item.QuantityBreakUOM </text>
),
grid.Column("BeginDate", "Begin Date", format: item =>string.Format("{0:d}", item.BeginDate)),
grid.Column("EndDate","End Date",format: item =>string.Format("{0:d}", item.EndDate)),
grid.Column(
header: "Price in PricingUOM",
format: item =>
{
var res = Html.FormatToDecimals((decimal)item.PriceInPricingUOM, (int)item.Numdecimals);
switch ((bool)#item.HasDetail)
{
case true:
return Html.ActionLink(res + " / " + (string)item.PricingUOM, "InquiryDetails", new { #id = #item.PriceMasterID }, new { #class = "item-link2", #id = "lnk_" + #item.PriceMasterID });
case false:
return Html.ActionLink(res+ " / " + (string)item.PricingUOM, null, null, new { onclick = "return NoDetailsDialog('" + #item.NoDetailReason + "')" });
}
return null;
}
),
grid.Column(
header: "Price Alt UOM",
format: #<text>#Html.FormatToDecimals((decimal)item.PriceInOrderUOM, (int)item.Numdecimals) / #item.OrderUOM </text>
),
grid.Column("Rolling12", "Rolling 12 Sales", format: #<text>#String.Format("{0:c0}", #item.Rolling12) </text>),
grid.Column("CMPercent", "Net CM ", format: #<text>#String.Format("{0:0.00} %", #item.CMPercent * 100) </text>)
))
</div>
</div>
<script type="text/javascript">
function NoDetailsDialog(message) {
alert(message);
return false;
}
</script>

You can use datatables. Please let me know how you progress with datatables and I can be available to help you through it,
I can even assist with razor syntax:
nuget DataTabes.net jquery plugin
bundles.Add(new StyleBundle("~/Content/CssGrid").Include(
"~/Content/DataTables/css/jquery.dataTables.min.css"));
bundles.Add(new ScriptBundle("~/bundles/JSGrid").Include(
"~/Scripts/DataTables/jquery.dataTables.min.js"));
JavaScript:
//perform tasks like initialize fields, show popup, and post to server
function DeleteMe()
function EditMe()
function Add()
Page:
$(document).ready(function() {
$('#theDataTable').DataTable();
} );
</script>
//button to show popup for add/edit here
<table id="theDataTable" class="display table table-striped table-bordered">
<thead>
<tr>
<th>Field Name A
</th>
<th>Field Name B
</th>
<th>Field Name C
</th>
</th>
<th>Delete
</th>
<th>Edit
</th>
</thead>
<tbody>
<% int rowCount = 0;
foreach (AClass item in Model.AClassList)
{ %>
<tr id="<%:rowCount%>">
<td><%:item.FieldA%></td>
<td><%:item.FieldB%></td>
<td><%:item.FieldC%></td>
<td>
<a href="#" title="Delete" class="btn btn-default btn-xs btn-block"
onclick="return DeleteMe('<%:item.Id%>')">Delete</a>
</td>
<td>
<a href="#" title="Edit" class="btn btn-default btn-xs btn-block"
onclick="return EditMe('',
'<%:item.FieldA %>',
'<%: Html.Encode(item.FieldB) %>',
'<%: Html.Encode(item.FieldC) %>')">Edit</a>
</td>
<% rowCount++;
} %>
</tr>
</tbody>
</table>

I have come across the same problem before. In my case it ended up being something to do with the MVC view resolver being scoped to the wrong folder due to calling a different controller than the one that had been used to construct the view which I was making the call in.
I know that's not much help, and it does seem peculiar as you have explicitly stated the controller name in your BeginForm statement. I had my mentor resolve the issue for me in the end, he did so by trial and error just commenting out the various lines until the problem was isolated.

Related

How to load a PartialView with a button click in ASP.NET MVC

I have a page that basically has two side-by-side divs. In the left div I will have an HTML table with several rows, and in each of those rows, I was trying to place a button that would Render Partial to the right div.
What I've tried below doesn't seem to be working correctly, when I click on the button, nothing is rendered to the right div and if I put a break in debug on the partial view it returns the view for every single row. How do I render the partial view on a button click and not have the partial view render automatically?
<div class="float-container">
<div class="float-childsmall">
#foreach (var watchList in Model.ViewExecutingTradesUserWatchListFollowShort)
{
<table id="customers">
<caption class="text-center"><h2>#watchList.WatchListName</h2></caption>
<caption class="text-center"><p style="font:10px;">#watchList.WatchListDescription</p></caption>
<tr>
<th>Ticker</th>
</tr>
#foreach (var ticker in Model.ViewUserWatchListTickerModel.Where(y => y.UserWatchListId == watchList.UserWatchListId).ToList())
{
<tr>
<td><a target="_blank" href="https://finviz.com/quote.ashx?t=#ticker.Ticker">#ticker.Ticker </a></td>
<td>
#{
<button data-url='#Html.Action("_Research", null, new ViewDataDictionary { { "ChartTicker", #ticker.Ticker } });'>
#Html.DisplayFor(modelItem => #ticker.Ticker)
</button>
<!--Html.RenderPartial("_Research", null, new ViewDataDictionary { { "ChartTicker", "META" } });-->
}
</td>
</tr>
}
</table>
}
</div>
<div class="float-child">
#{
Html.RenderPartial("_Research", null, new ViewDataDictionary { { "ChartTicker", "META" } });
}
</div>
</div>
Here is the action
public ActionResult _Research()
{
return PartialView("_Research");
}

delete from model don't work correctly

i have a repeating table in razor mvc , my model is an array
#model Models.Event[]
when i delete any row , every thing is ok and i check data in break point...
but view can't render data correctly and always last row is deleted.
in my code, i want to delete row index 2 ... i give it as hard code , in controller and view true data is passed but at the end, in view (display page) , the last row is deleted and the row with index 2 is there again :(
i pass my model from an partial view to the main page.
here is my javascript codes:
<script type="text/javascript">
$(document)
.ready(function () {
$("#EventsTbl")
.on("click", "tbody .btn-delrow",
function () {
var deletedrow = $(this).closest("tr");
var index = 2; // deletedrow.attr("data-ownum");
var data = $("#edit-Event-form").serialize();
deleteEvent(data, index);
});
function deleteEvent(data,index) {
if (confirm("Do you want to delete product: " + index)) {
var postdata = data;
$.post('/Events/DeleteDetailRow', postdata,
function (response) {
$("#EventsTbl tbody").html(response);
});
}
}
});
</script>
and in controller we have :
[HttpPost]
public ActionResult DeleteDetailRow(Event[] model)
{
var list = new List<Event>(model);
list.RemoveAt(2);
return PartialView("AllDetailRows", list.ToArray());
}
"list" has true data after delete, but i don't know where is the problem. at AllDetailRows model has true data too.
here is my partial view code : (AllDetailRows)
#model Models.Event[]
#for (int i = 0; i < Model.Length; i++)
{
<tr data-rownum="#i">
<td class="input">
#Html.EditorFor(model => model[i].EventExp,new {value=Model?[i]?.EventExp})
#Html.ValidationMessageFor(model => model[i].EventExp, "", new { #class = "text-danger" })
</td>
<td>
<button class="btn btn-sm btn-danger btn-delrow" type="button">
<i class="fa fa-remove"></i>
</button>
</td>
</tr>
}
and this is my main view :
#model Models.Event[]
#* This partial view defines form fields that will appear when creating and editing entities *#
<fieldset>
<div>
<table class="table table-bordered table-striped" id="AdverseEventsTbl">
<thead>
<tr>
<th class="text-center or-bold" style="width: 10%">#Html.LabelFor(model => model.First().EventExp)</th>
<th style="width: 5%">
<button class="btn btn-sm btn-success btn-addrow" type="button">
<i class="fa fa-plus-square"></i>
</button>
</th>
</tr>
</thead>
<tbody>
#Html.Partial("AllDetailRows", Model)
</tbody>
</table>
</div>
</fieldset>
any idea?
thanks is advance

How to pass value of particular row to controller method in asp .net mvc

I need to send send value of particular row to controller method on clicking of anchor buttons. Also I need functionality to filter data based on dropdown selection(Working fine). I am newbie to asp mvc, Do not know if I am doing right if there is any BETTER solution without Jquery tables please suggest.
Here is my view structure:
#using (Html.BeginForm("Index", "Manage_Menu", FormMethod.Post, new { id = "myForm" }))
{<div style="float:left;padding-bottom:10px;">
<b>Select Parent Page</b>
<div>
#Html.DropDownList("ddlPageId", (IEnumerable<SelectListItem>)ViewBag.PageDDL, "Select parent page", new { onchange = "this.form.submit();" })
</div>
</div>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.PageName)
</th>
<th>
#Html.DisplayNameFor(model => model.IsActive)
</th>
<th>
#Html.DisplayNameFor(model => model.ShowInMenu)
</th>
<th>Move Menu Position</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.PageName)
</td>
<td>
<a href="javascript:void()" onclick="sumitForm()">
<input type="hidden" name="mmmm" value="#item.Id" />
#if (item.ShowInMenu == true)
{
<span class="glyphicon glyphicon-ok text-success" aria-hidden="true"></span>
}
else
{
<span class="glyphicon glyphicon-remove text-danger" aria-hidden="true"></span>
}
</a>
</td>
<td>
<a href="javascript:void()" onclick="sumitForm()">
#if (item.ShowInMenu == true)
{
<span class="glyphicon glyphicon-ok text-success" aria-hidden="true"></span>
}
else
{
<span class="glyphicon glyphicon-remove text-danger" aria-hidden="true"></span>
}
</a>
</td>
<td>
<a href="javascript:void()" onclick="sumitForm()">
<span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
</a>
<a href="javascript:void()" onclick="sumitForm()">
<span class="glyphicon glyphicon-arrow-down" aria-hidden="true"></span>
</a>
</td>
</tr>
}
</table>
<script>
function sumitForm() {
document.getElementById("myForm").submit();
}
</script>
}
Here is my Controller:
public ActionResult Index()
{
var pages = db.PageMains.Where(a => a.ParentPageId == 0); ;
ViewBag.PageDDL = new SelectList(db.PageMains.Where(r => r.ParentPageId == 0), "Id", "PageName");
return View(pages);
}
[HttpPost]
public ActionResult Index(FormCollection aa)
{
if (!string.IsNullOrEmpty(aa["ddlPageId"]))
{
int filter = Convert.ToInt32(aa["ddlPageId"]);
var pages = db.PageMains.Where(a => a.ParentPageId == filter);
ViewBag.PageDDL = new SelectList(db.PageMains.Where(r => r.ParentPageId == 0), "Id", "PageName", filter);
return View(pages);
}
else
{
var pages = db.PageMains.Where(a => a.ParentPageId == 0); ;
ViewBag.PageDDL = new SelectList(db.PageMains.Where(r => r.ParentPageId == 0), "Id", "PageName");
return View(pages);
}
}
I have tried to store values inside hidden field but whenever I press any anchor button it is sending all the values.
Here is my page design:
What #Stephen Muecke is suggesting is the ideal situation to update the content in one action.
However, sometimes we need to update content in real time. So to handle your case jQuery is the best bet. Since you asked to do it using MVC, below is the proposed solution (Ironically, under the hood jQuery is doing the work for you)
You need to use #Ajax.ActionLink method provided in MVC to make ajax calls. To make it a real Ajax, you need to add reference to jquery.unobtrusive-ajax.min.js. Otherwise it will fallback to Postback request
E.g.
Script Reference needs to be added.
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
Your action button in view would look like:
#Ajax.ActionLink("Click Me", "Clicked", "Home", new { id = item.pageId})
Action Method
public void Clicked(string id)
{
//Save the page ID in database. I keep it simple but if you want, you can return the status too.
}
One drawback of using #Ajax.ActionLink is, you cannot set html inside anchor tag like you did in your example (e.g. span tag). If you want to achieve that too refer here
The problem here is that you have a single form and all the anchors have the code to submit the form on click. So your click on any of the anchors lead to entire form submission - hence submitting all the data.
If you want partial data submission you can very well use ajax post. Pass the value using the ajax post and based on the return from controller update the table.
Since you are new to the technology I would suggest taking some time to read about ajax posts: https://api.jquery.com/jquery.post/
Also for more dynamic client side bindings you can use client side frameworks like AngularJS
OR
A very bad way would be to have forms for all the rows and name them based on the element's Id and on click submit only the form specific to the row. But this would be pathetic code.

HOw to link table to #Html.ActionLink

I have program in mvc which fetch data from controller and then display in view.It makes dynamic table with data in it. Inside it there is a link "SEE DETAILS", but instead of a single link i want to make whole table as a link like :
#Html.ActionLink("SEE DETAILS", "AppDetail", new { #id = item.id, appnameformp = item.AppNameForMP }, new { #style = "color:#C55000;font-size: 11px;text-decoration:none;" })
but i don't know how to do it...Any help is really appreciated and thanks in advance.
<div class="grid_9.5 alpha">
#foreach (var item in Model)
{
<div class="grid_4 alpha box_shadow" id="featured-subbillboard" style="margin-bottom:10px;" >
<table>
<tr >
<td><img height="140" width="130" src=#item.imgfile />
</td>
<td> </td>
<td class="table">
<h1 class="heading1" style="margin-top:10px; line-height: .4em;">#item.AppNameForMP </h1>
<h2 class="heading2">#item.DevName </h2>
<br />
<p class="para">
#if (item.AppDesc.Length > 50)
{#item.AppDesc.Remove(#item.AppDesc.Length -50)}
else
{ #item.AppDesc}
</p>
#Html.ActionLink("SEE DETAILS", "AppDetail", new { #id = item.id, appnameformp = item.AppNameForMP }, new { #style = "color:#C55000;font-size: 11px;text-decoration:none;" })
</td>
</tr>
</table>
</div>
}
</div>
Just use a regular anchor tag, and use #Url.Action() to get the href:
<a href="#Url.Action("AppDetail")">
<!-- table here -->
</a>
Also, note that while block-level links are now supported in HTML5, browser support and even implementation is not consistent. Some will handle linking the whole table well, while others will do all kinds of weird stuff. Just something to be aware of.

Refresh User Control in MVC

I have 3 user controls in an aspx page in my MVC application.
i bind data from DB from one controller.
on the selection of "Filter / Status" i want to bind data (refresh) to "List" user control with out refreshing "Filter & Status" user controls.
below are my user controls in aspx page.
please help me how to refresh part of the page/user control.
i have tried by returning only "ListView" View data. but its searching for the other 2 views & throwing exception.
<td>
<%Html.RenderPartial("Filter", ViewData["FilterView"]); %>
</td>
<td valign="top" width="15%">
<%Html.RenderPartial("Status", this.ViewData["StatusView"]); %>
</td>
<td valign="top" width="85%">
<%Html.RenderPartial("List", this.ViewData["ListingView"]); %>
</td>
do sth like this
html (aspx page):
<div id="ListingView">
<%Html.RenderPartial("List", this.ViewData["ListingView"]); %>
</div>
...
<input type="button" id="refreshListingView" />
javascript to handle it:
$('#refreshListingView').click(function () {
var selectedStatusId = 'get here proper status id';
$.ajax({
url: '/YourController/GetListingView',
type: "GET",
data: { "statusId": selectedStatusId },
success: function (response) {
$('#ListingView').html(response);
}
});
});
YourController:
[HttpGet]
public ActionResult GetListingView(int statusId)
{
ViewData["ListingView"] = your data filtered by statusId or what you want;
return PartialView("List",ViewData["ListingView"]);
}
Instead of ViewData["ListingView"] I would use dedicated model, but it's just an example. It should work.

Resources