Model is null in controller action after ajaxPost in partial page - c#

I am new to ASP mvc
I have a partial page like
#model IEnumerable<Sample.Models.Privilege>
#{
ViewBag.Title = "Details";
}
<script type="text/javascript">
function UpdatePrivilegeSuccess() {
}
function UpdatePrivilegeFailure() {
}
</script>
<div class="settingsTable" style="position: relative; width: 100%; margin: 0 auto">
<div style="width: 50%; margin: 0 auto">
<div style="width: 50%; margin: 0 auto">
<h2>Privilege</h2>
</div>
</div>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.PrivilegeName)
</th>
<th>
#Html.DisplayNameFor(model => model.module.ModuleName)
</th>
<th>
#Html.Label("Option")
</th>
<th>Action</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.PrivilegeName)
</td>
<td>
#Html.DisplayFor(modelItem => item.module.ModuleName)
</td>
<td>
#Html.CheckBoxFor(modelItem => item.Checked)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.PrivilegeId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.PrivilegeId })
</td>
</tr>
}
</table>
#using (Ajax.BeginForm("UpdatePrivilege", "RolePrivilegemapping",
new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "PrivilegeWrapper",
OnSuccess = "UpdatePrivilegeSuccess",
OnFailure = "UpdatePrivilegeFailure"
}))
{
<p>
<input type="submit" value="Update" />
</p>
#Html.ActionLink("Update", "UpdatePrivilege", "RolePrivilegemapping")
}
</div>
I am listing privileges in a table. But after the user click Update for updating model , Model is received as NULL in controller action
public ActionResult UpdatePrivilege(IEnumerable<sample.Models.Privilege> updatedPrivilege
{
return PartialView("_Privilege", One_Track.Models.DataProvider.OneTrackDataProvider.GetPtrackPrivilegeNames());
}
Why is this happening? Any help will be appreciated

You need to at least move the data that your posting into your form or nothing will be posted.
You will also need to index your collections so that the modelbinder will work.
This is done by using a for loop rather than a foreach.
If you need non-editable fields to re-bind you will have to provide them as hidden inputs. You can use HiddenFor for this. See them under the DisplayFor's below.
#using (Ajax.BeginForm("UpdatePrivilege", "RolePrivilegemapping",
new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "PrivilegeWrapper",
OnSuccess = "UpdatePrivilegeSuccess",
OnFailure = "UpdatePrivilegeFailure"
}))
{
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.PrivilegeName)
</th>
<th>
#Html.DisplayNameFor(model => model.module.ModuleName)
</th>
<th>
#Html.Label("Option")
</th>
<th>Action</th>
</tr>
#for(var i = 0; i < Model.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => modelItem[0].PrivilegeName)
#Html.HiddenFor(modelItem => modelItem[0].PrivilegeName)
</td>
<td>
#Html.DisplayFor(modelItem => Model[0].ModuleName)
#Html.HiddenFor(modelItem => modelItem[0].ModuleName)
</td>
<td>
#Html.CheckBoxFor(modelItem => Model[0].Checked)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.PrivilegeId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.PrivilegeId })
</td>
</tr>
}
</table>
<p>
<input type="submit" value="Update" />
</p>
}

Related

Whats the best way of using ajax jquery to load partial views onto a specific page?

I have a index page the code looks like this
#model PagedList.IPagedList<PartialViews.Models.Customer>
#using PagedList.Mvc
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<div class="container">
<table class="table">
<tr>
<th>
Title
</th>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Email Address
</th>
<th>
Phone Number
</th>
<th>
Modified Date
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmailAddress)
</td>
<td>
#Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
#Html.DisplayFor(modelItem => item.ModifiedDate)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.CustomerID }) |
#Html.ActionLink("Details", "Details", new { id = item.CustomerID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.CustomerID })
</td>
</tr>
}
</table>
#Html.PagedListPager(Model,page=>Url.Action("Index",new{page,pageSize=Model.PageSize}))
</div>
My CustomersController has this code
private AdventureWorksLT2012Entities db = new AdventureWorksLT2012Entities();
// GET: Customers
public ActionResult Index(int page=1, int pageSize=10)
{
List<Customer> customers = db.Customers.ToList();
PagedList<Customer> cust = new PagedList<Customer>(customers,page,pageSize);
return View(cust);
//return View(db.Customers.ToList());
}
Heres the Main page where i want the Customers List from the Index action to be shown
#model PartialViews.Models.Customer
#{
ViewBag.Title = "Main";
}
<body>
<div class="container">
<h2>Customer's List</h2>
<div id="dvCustomerDetails" style="width: 50%; height: 130px;display: none"></div>
</div>
</body>
<script type="text/javascript">
$.ajax({
url: 'Customers/Index',
contentType: 'application/html;',
type: 'GET',
dataType:'html'
})
.success(function(result) {
$('#dvCustomerDetails').html(result);
})
</script>
I want to display this table onto a new page as a partial view using ajax jquery but I am having trouble implementing it.
I was able to use RenderPartial method to display it as a partial view but i am having trouble doing it with ajax. Any help or suggestion will be appreciated.

Aligning columns in MVC4 Index.cshtml

This is a web application MVC4 with EF6 with Code First Migration.
I'm having issues with the alignment of my columns. I added arrows to show where I want each of the titles to be.
What code do I need to add in to make them align properly?
Views\Users\Create.cshtml
#using PagedList;
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#model IPagedList<RecreationalServicesTicketingSystem.Models.User>
#{
ViewBag.Title = "Users";
}
<h2>Users</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using (Html.BeginForm("Index", "Users", FormMethod.Get))
{
<p>
Find by name: #Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
<input type="submit" value="Search" />
</p>
}
<table>
<tr>
<th>
First Name
</th>
<th>
#Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.NameSortParm })
</th>
<th>
#Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm })
</th>
<th></th>
<th>
Department ID
</th>
<th>
Depot ID
</th>
<th>
Is Administrator
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Department.DepartmentName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Depot.DepotName)
</td>
<td>
#Html.DisplayFor(modelItem => item.IsAdministrator)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.UserID }) |
#Html.ActionLink("Details", "Details", new { id=item.UserID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.UserID })
</td>
</tr>
}
</table>
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
It looks like you have an empty
<th></th>
tag in the middle of your header row. You probably want to move that to the end of the header row where the CRUD links are.
<tr>
<th>
First Name
</th>
<th>
#Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.NameSortParm })
</th>
<th>
#Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm })
</th>
<th>
Department ID
</th>
<th>
Depot ID
</th>
<th>
Is Administrator
</th>
<th></th>
</tr>
You need to use the thead and tbody tags:
<table>
<thead>
<tr>
<th>/* Your column names*/ </th>
/* ... */
</tr>
</thead>
<tbody>
/*... */
</tbody>
</table>

IsAjaxRequest() is always false and partial view will not reload

I have looked at every other stackoverflow post and none of them work.
This is the bit in my Browse page
#using (Ajax.BeginForm("Browse", "Store",
new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "this"
}))
{
#Html.TextBox("searchString")
<input type="submit" value="Search"/>
}
<div id="this">
#Html.Partial("_Listings", Model)
</div>
This is my bundle
bundles.Add(new ScriptBundle("~/bundles/shell").Include(
"~/Scripts/jquery-{version}.js",
"~/Scripts/jquery-ui-{version}.js",
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/jquery.validate*"));
This is in my _Layout file
#Scripts.Render("~/bundles/shell")
And this is the partial view that should be refreshed when I click the Search button
<div id="listings">
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th>
#Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<div class="text-right">
<tr>
<td>
<h1>#Html.DisplayFor(modelItem => item.Title)</h1>
</td>
<td>
<h1> #Html.DisplayFor(modelItem => item.Description)</h1>
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td></td>
</tr>
</div>
}
</table>
</div>
I can't quite figure out what is going wrong. The controller is fine because the whole page refreshes with the searchString, but I can't get the div with id="this" to reload. I'm pretty sure my bundles are correct.
Controller
[HttpPost]
public ActionResult Browse(string searchString)
{
var model = storeRepo.AllProducts(searchString).Take(10);
if (new HttpRequestWrapper(System.Web.HttpContext.Current.Request).IsAjaxRequest())
{
Debug.WriteLine("IsAjax");
return PartialView("_Listings", model);
}
return View("Browse", model);
}

ASP.NET MVC save button loading but not working

I have implemented a save button in my .NET application on the index page. When I click it, it loads, but does not save anything. I am just using the index page for checkboxes. If I uncheck something and save it, it saves, but also unchecks everything else in that row. Nothing happens when I try to check something. Here is the code I'm using:
Index.cshtml
#using (Html.BeginForm("save", "drnos"))
{
<input type="submit" value="Save" />
}
An example of one of my check box fields:
<td>
#Html.EditorFor(modelItem => item.Soft)
#Html.ValidationMessageFor(modelItem => item.Soft)
</td>
drnosController.cs
[HttpPost]
public ActionResult save(Doctor doc)
{
System.Diagnostics.Debug.WriteLine("Save Called");
db.Entry(doc).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
Here is the whole HTML file:
#model PagedList.IPagedList<drnosv6.Models.Doctor>
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "Index";
}
<h2>Doctors</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using (Html.BeginForm()) //insert the search bar
{
<p>
Find by First Name, Last Name, or RVH ID: #Html.TextBox("SearchString")
<input type="submit" value="Search" />
</p>
}
#using (Html.BeginForm("save", "drnos"))
{
<input type="submit" value="Save" />
}
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('tr:even').addClass('alt-row-class');
});
</script>
<p>
</p>
<p>Click on a column header to sort by that column</p>
<table>
<tr>
<th>
#Html.ActionLink("RVH ID", "Index", new { sortOrder = ViewBag.IDSortParm })
</th>
<th>
#Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.LastSortParm })
</th>
<th>
#Html.ActionLink("First Name", "Index", new { sortOrder = ViewBag.FirstSortParm })
</th>
<th>
Middle Initial
</th>
<th>
Degree
</th>
<th>
Group
</th>
<th>
Adm Priv
</th>
<th>
#Html.ActionLink("QCPR", "Index", new { sortOrder = ViewBag.QCPRSortParm })
</th>
<th>
#Html.ActionLink("Keane", "Index", new { sortOrder = ViewBag.KeaneSortParm })
</th>
<th>
#Html.ActionLink("Orsos", "Index", new { sortOrder = ViewBag.OrsosSortParm })
</th>
<th>
#Html.ActionLink("Soft", "Index", new { sortOrder = ViewBag.SoftSortParm })
</th>
<th>
#Html.ActionLink("3M", "Index", new { sortOrder = ViewBag.threeMSortParm })
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
using (Html.BeginForm("Save", "Doctor", FormMethod.Post))
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.RVH_ID_)
</td>
<td>
#Html.DisplayFor(modelItem => item.Last_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.First_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Middle_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Degree1)
</td>
<td>
#Html.DisplayFor(modelItem => item.Group)
</td>
<td>
#Html.DisplayFor(modelItem => item.AdmPriv)
</td>
<td>
#Html.DisplayFor(modelItem => item.QCPR)
</td>
<td>
#Html.EditorFor(modelItem => item.Keane)
#Html.ValidationMessageFor(modelItem => item.Keane)
</td>
<td>
#Html.EditorFor(modelItem => item.Orsos)
#Html.ValidationMessageFor(modelItem => item.Orsos)
</td>
<td>
#Html.EditorFor(modelItem => item.Soft)
#Html.ValidationMessageFor(modelItem => item.Soft)
</td>
<td>
#Html.DisplayFor(modelItem => item.C3M)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.RVH_ID_ })
#Html.ActionLink("Details", "Details", new { id = item.RVH_ID_ })
</td>
</tr>
}
}
</table>
<p>
<input type="submit" value="Save" />
</p>
<br />
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
Your BeginForm or ActionLink has to point to ActionResult Edit.
When a form is submitted, only the inputs declared within that form get submitted. You only have the submit button in your form, so there are no other fields to fill out your Doctor structure. You need to have your save button on the same form as all your other fields.

Asp.Net - EF - MVC - Indexing Rows

I am using Asp.Net , EF6 ( MVC ) and have some data stored in my view. What I need is some indexing for each row. Here is the view.
For every row I have 0 Index. I wanna know, if there is some Built in feature in EF, that will help to add indexes for each row, (1,2,3....) and which will be automatically be updated, when new rows are created or deleted.
This is the Code for creating the table and doing Paging in my View.
<div class="bs-example">
<div class="table-responsive">
<div class="panel panel-default">
<table class="table table-striped table-hover table-bordered" cellspacing="0" data-toggle="table" data-click-to-select="true">
<tr>
<th style="vertical-align:middle;" class="text-center">
Index
</th>
<th style="vertical-align:middle;" class="text-center">
#Html.ActionLink("English", "Index", new { sortOrder = ViewBag.EnglishSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th style="vertical-align:middle;" class="text-center">
#Html.ActionLink("Russian", "Index", new { sortOrder = ViewBag.RussianSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th style="vertical-align:middle;" class="text-center">
#Html.ActionLink("Armenian", "Index", new { sortOrder = ViewBag.ArmenianSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th style="vertical-align:middle;" class="text-center">
#Html.ActionLink("French", "Index", new { sortOrder = ViewBag.FrenchSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th style="vertical-align:middle;" class="text-center">
#Html.ActionLink("Spanish", "Index", new { sortOrder = ViewBag.SpanishSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th style="vertical-align:middle;" class="text-center">
#Html.ActionLink("Arabic", "Index", new { sortOrder = ViewBag.ArabicSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th></th>
</tr>
#{
foreach (var item in Model.Item1)
{
<tr class="clickableRow">
<td style="vertical-align:middle; font-size:medium;font-style:italic;" class="text-center">
#ViewBag.IndexOfRow.ToInt32
</td>
<td style="vertical-align:middle;" class="text-center">
#Html.DisplayFor(modelItem => item.English)
</td>
<td style="vertical-align:middle;" class="text-center">
#Html.DisplayFor(modelItem => item.Russian)
</td>
<td style="vertical-align:middle;" class="text-center">
#Html.DisplayFor(modelItem => item.Armenian)
</td>
<td style="vertical-align:middle;" class="text-center">
#Html.DisplayFor(modelItem => item.French)
</td>
<td style="vertical-align:middle;" class="text-center">
#Html.DisplayFor(modelItem => item.Spanish)
</td>
<td style="vertical-align:middle;" class="text-center">
#Html.DisplayFor(modelItem => item.Arabic)
</td>
<td style="vertical-align:middle;" class="text-center">
<span style="color:white;">
#Html.ActionLink("Edit", "Edit", new { id = item.Text, #style = "color:red;" })
#*#Html.ActionLink("Details", "Details", new { id = item.Text })*#
#Html.ActionLink("Delete", "Delete", new { id = item.Text })
</span>
</td>
</tr>
}
}
</table>
</div>
<br />
Page #(Model.Item1.PageCount < Model.Item1.PageNumber ? 0 : Model.Item1.PageNumber) of #Model.Item1.PageCount
#Html.PagedListPager(Model.Item1, page => Url.Action("Index",
new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
</div>
</div>
And this is the code from my Controller
public ViewResult Index(int? page)
{
int pageSize = 15;
int pageNumber = (page ?? 1);
var allModels = new Tuple<IPagedList<Translation>, List<Translation>>
(translations.ToPagedList(pageNumber, pageSize), translations.ToList()) { };
return View(allModels);
}
I have removed the unnecessary code, only is left the code for paging.
I have not done anything so far, because I have not find any indexing question or article in Google or SO so far.
Thanks for help.
And if you want to put Index while creating table, you can loop like this in your table body:
<tbody>
#{
int counter = 1;// Index start value
foreach (var Item in Model.SomeList)
{
<tr>
<td> #counter </td>
</tr>
counter++;
}
}
</tbody>
Just set the start row index in the action method to ViewBag.
int pageSize = 15;
int pageNumber = (page ?? 1);
ViewBag.StartRowIndex = ((pageNumber - 1) * pageSize) + 1;
Then use it in the view.
#{
var rowIndex = (int)ViewBag.StartRowIndex;
}
foreach (var item in Model.Item1)
{
<tr class="clickableRow">
<td style="vertical-align:middle; font-size:medium;font-style:italic;" class="text-center">
#(rowIndex++) //#ViewBag.IndexOfRow.ToInt32
</td>
When you dont know what to do, create a new class :))
Im kidding, but the idea remains valid.
Why dont you craete a new class that will represent your "ViewModel" that will have the exact EF model inside and an extra Index property that you will use to bind to an index in the view?
What you will pass from your controller to the view will be the new ViewModel class.
Note:
If you want to go fancy, you could go somewhere on the line of : ObservableCollection http://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx which derrives from INotifyPropertyChanged
Basically it means that you have an event at your disposal that you can fire when the list has changed (add, delete) that will be used to update the index.

Categories

Resources