Passing value to partial view via post - c#

I want to pass a long string from my View to a partial View and render the partial View on Button click.
The string is too long to be passed as a part of the url, so it must be passed via post.
On the click of the Button Details, an ajax function is called, which should pass the required parameter to the partial view and render it.
Unfortunytely this doesn't work, it seems I have an error in my ajax-declaration. When I click the Details Button nothing happens, and the debugger jumps over the ajax declaration.
Here is a part of my View:
<form class="form-inline" asp-controller="Order" asp-action="Details">
<table class="ComplianceTable" id="ComplianceTable">
<thead>
<tr id='tableHeader'>
<th>Res.</th>
<th>Trend</th>
<th>Portfolio</th>
<th>Level</th>
<th>Code</th>
<th>Description</th>
<th>Rule</th>
<th>Test Type</th>
<th>Limit</th>
<th>Result</th>
<th>(Previous)</th>
<th>Severity</th>
<th>Details</th>
</tr>
</thead>
<tbody>
#foreach (var info in Model.ViolationInfo)
{
<tr>
<td>#info.RuleType</td>
<td></td>
<td>#Model.code</td>
<td></td>
<td></td>
<td></td>
<td>#info.RuleName</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>
<input type="hidden" id="value1" name="info.Diagnostic">
<button class="btn js-details" type="button" name="Details" data-id="#info.Diagnostic">
Details
</button>
</td>
</tr>
<tr class="info"><td colspan="11">#info.Diagnostic</td></tr>
}
</tbody>
</table>
<div id="getComplianceDetails"></div>
</form>
Here is my PartialView:
#model string
<div id="getComplianceDetails">
<p>Test</p>
<p>
#Model
</p>
</div>
Here is my javascript:
$(document).ready(function () {
$(document).on('click', '.js-details', function (event) {
$("#ComplianceTable tr").removeClass("selected");
$(this).closest('tr').addClass('selected');
var $element = $(event.currentTarget);
var id = $element.data('id');
$.ajax({
url: '#Url.Action("Details", "Order")',
data: {info: id},
type: "POST",
success: function (data) {
$('#getComplianceDetails').html(data);
}
});
});
});
Here is my OrderController:
public ActionResult Details(string info)
{
return PartialView("~/Views/Shared/complianceDetails.cshtml", info);
}

Assuming that your "info" has value, try an explicit url:
url: '/Order/Details',
and maybe you need to add [FromBody] to your action:
public ActionResult Details([FromBody] string info)
{
return PartialView("~/Views/Shared/complianceDetails.cshtml", info);
}

Related

How to pass an array from one view and action to another in ASP.NET MVC?

What I want to achieve:
I want a feature that selects multiple records from the index page on my asp.net mvc website which are redirected to another webpage, where they can be bulk edited.
I am using checkboxes to do this, but I don't know how I can access the contents of this array from another action and view.
For now, this is the code that I have done:
The Index View:
#model IEnumerable<BulkDelete.Models.Employee>
#TempData["employeeIdsToDelete"];
<div style="font-family:Arial">
#using (Html.BeginForm("checking", "Home", FormMethod.Post))
{
<table class="table">
<thead>
<tr>
<td>Checkbox<br /></td>
<th>Name</th>
<th>Gender</th>
<th>Email</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td><input type="checkbox" name="employeeIdsToDelete" id="employeeIdsToDelete" value="#item.ID" /></td>
<td>#item.Name</td>
<td>#item.Gender</td>
<td>#item.Email</td>
</tr>
}
</tbody>
<br />
</table>
<input type="submit" value="Delete selected employees" />
}
</div>
The Controller Actions:
public class HomeController : Controller
{
SampleDBContext db = new SampleDBContext();
public ActionResult Index()
{
return View(db.Employees.ToList()) ;
}
[HttpPost]
public ActionResult UpdateMultipleRecords(IEnumerable<int> employeeIdsToUpdate)
{
return checking(employeeIdsToUpdate);
}
public ActionResult checking(IEnumerable<int>employeeIdsToUpdate)
{
foreach (var e in employeeIdsToUpdate)
{
Employee em = new Employee();
em = db.Employees.Find(e);
em.Name = ViewBag.Signature;
db.Entry(em).State = EntityState.Modified;
db.SaveChanges();
}
return View();
}
Instead of posting to index page. post the form in another page.
#using (Html.BeginForm("{actionNameOfAnotherPage}", "{anotherPageControllerName}", FormMethod.Post))
As you are posting an array of data, Use array indexing for form inputs.
#{ var index = 0;}
#foreach (var item in Model)
{
<tr>
<td><input type="checkbox" name="[#index]employeeIdsToDelete" class="mycheckbox" id="employeeIdsToDelete" value="#item.ID" /></td>
<td>#item.Name</td>
<td>#item.Gender</td>
<td>#item.Email</td>
</tr>
#{
index++;
}
}
You can also send them as an Ajax call, and in this scenerio you can also do this without a form.
<div style="font-family:Arial">
<table class="table">
<thead>
<tr>
<td>Checkbox<br /></td>
<th>Name</th>
<th>Gender</th>
<th>Email</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td><input type="checkbox" name="employeeIdsToDelete" class="mycheckbox" id="employeeIdsToDelete" value="#item.ID" /></td>
<td>#item.Name</td>
<td>#item.Gender</td>
<td>#item.Email</td>
</tr>
}
</tbody>
<br />
</table>
<input type="button" onClick="deleteEmployees()" value="Delete selected employees" />
</div>
and below your html page
<script>
function deleteEmployees() {
var checkboxes = document.getElementsByClassName("mycheckbox");
var checkedValues = [];
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
console.log(i);
checkedValues.push(checkboxes[i].value)
}
}
console.log(checkedValues);
$.ajax({
type: "POST",
url: '#Url.Action("YourAction", "YourController")',
data: { employeeIdsToUpdate: checkedValues },
success: function (res) {
if (res.ok) {
window.location = res.returnURL;
}
},
error: function (req, status, error) {
console.log(error);
}
});
}
</script>
and in your POST ACTION you can take these values
[POST]
public ActionResult UpdateEmployees(int[] employeeIdsToUpdate)
{
foreach (int e in employeeIdsToUpdate)
{
Employee em = new Employee();
em = db.Employees.Find(e);
em.Name = ViewBag.Signature;
db.Entry(em).State = EntityState.Modified;
db.SaveChanges();
}
return Json(new { ok = true, returnURL = Url.Action(nameof("YOUR VIEW IN HERE"))});
}
Here are some options for sending array from a View to some controller action:
Post the form to your controller action
Send ajax call to your controller action
MVC Hyperlink pointing to your controller action
Here are some options for sending array from a controller action to some other controller action:
Save data in TempData (its available across controllers)
Save data in browser memory (Temp Storage)
Save data in DB
Save data in Session object
Save data in Cache object
and Please dont forget to mark this as answer ... thanks

Error for bind data values in html.index with AngularJS

i am using AngularJS and I am not able to populate the data in index.view with the ng-repeat of angular.
I'll leave the code snippet for any help.
Remember, I have the status of the http 200 requests ok, just when I connect the data on the screen, I can not fill.
registerController.js
angular.module('Application').controller('registerController',
function($scope,
$http, registerService) {
$scope.registerUser = {};
$scope.GetAllRegisters = function () {
var registerServiceCall = registerService.GetRegisters();
registerServiceCall.then(function (results) {
$scope.registers = results.data;
}, function (error) {
$log.error('ERRO');
});
};
$scope.GetAllRegisters();
});
My service.js
angular.module('Application').factory('registerService', function ($http) {
return {
GetRegisters: function () {
return $http({
method: 'Get',
url: "http://localhost:51734/api/UserAPI"
})
},
};
});
And my index.html
<div class="row" style="">
<table class="table table-striped" style="">
<tbody>
<tr>
<th style="display:none">Id</th>
<th>Nome</th>
<th>Sobrenome</th>
<th>Ativo</th>
<th>Email</th>
<th>Editar</th>
<th>Remover</th>
</tr>
<tr ng-repeat="registerUser in registers" style="word-wrap: break-word;">
<td style="display:none">{{registerUser.UserId}}</td>
<td>{{registerUser.Name}}</td>
<td>{{registerUser.LastName}}</td>
<td><input type="checkbox" ng-model="registerUser.IsActive" disabled /></td>
<td>{{registerUser.Email}}</td>
<td>
<td>
</td>
</tr>
</tbody>
</table>
Any help or advice would be appreciated. Thanks
What is $scope.registers once the page loads?
As it stands right now your table will not render correctly because you cannot use ng-repeat on a tr because it will be inserted as a block-level element which will blow up your table. However, the data should still be inserted above your table. You will have to call ng-repeat on a custom directive to render the table properly.
Something like this:
<register-user-row ng-repeat="registerUser in registers"><register-user-row>
Then in the directive:
angular.module('Application').directive('regusterUserRow', function() {
return {
templateUrl: "directive path here",
restrict: "E",
scope: true
}
})
And the directive's html:
<tr style="word-wrap: break-word;">
<td style="display:none">{{registerUser.UserId}}</td>
<td>{{registerUser.Name}}</td>
<td>{{registerUser.LastName}}</td>
<td><input type="checkbox" ng-model="registerUser.IsActive" disabled /></td>
<td>{{registerUser.Email}}</td>
<td>
</td>
<td>
</td>
</tr>
Note: You were also missing a closing after your first link in the .

I want to serialize form data using jquery

Hello guys i working on data serialize using jquery
i have pasted my HTML code below.
HTML
<div class="row">
<div class="col-md-12 col-sm-12">
<div class="ibox-content">
<form id="product">
<table class="table">
<thead>
<tr>
<th>Action</th>
<th>Product Name</th>
<th>Price</th>
<th>Qty</th>
<th>Total</th>
</tr>
</thead>
<tbody>
#foreach (var _product in Model.ProductList)
{
<tr>
<td>Details</td>
<td>
<strong>
#_product.name
<input type="hidden" name="productId" value="#_product.productId" />
</strong>
</td>
<td id="price">#_product.wholesalePrice</td>
<td id="quantity"><input style="width:50px;" name="qty" value="0"><input type="hidden" name="total" id="rowTotal" /></td>
<td id="value"></td>
</tr>
}
</tbody>
</table>
</form>
<div class="ibox-content">
<button id="totalCal" class="btn btn-primary pull-right">Calculate</button>
</div>
<table class="table invoice-total">
<tbody>
<tr>
<td><strong>Sub Total :</strong></td>
<td id="result">$1026.00</td>
</tr>
<tr>
<td><strong>Shipping :</strong></td>
<td id="Shipping">$235.98</td>
</tr>
<tr>
<td><strong>TOTAL :</strong></td>
<td id="finalTotal">$1261.98</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
Jquery function
function GetTblRow() {
var data = $("#product").serializeArray();
var from = JSON.stringify(data);
console.log(from);
};
Output
[{"name":"productId","value":"1"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"2"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"3"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"4"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"5"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"6"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"7"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"8"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"9"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"10"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"12"},{"name":"qty","value":"0"},{"name":"total","value":"0"},{"name":"productId","value":"13"},{"name":"qty","value":"0"},{"name":"total","value":"0"}]
Expected Output
[{"ProductId":"1","qty":"0","total":"0"},"ProductId":"1","qty":"0","total":"0"},{"ProductId":"2","qty":"0","total":"0"},{"ProductId":"3","qty":"0","total":"0"},{"ProductId":"4","qty":"0","total":"0"}]
i did above code for serialize form data but i can not get above expected output. So can you help me with this?
you cannot directly use serializeArray() to get the expected json you have to separate the expected result from array
<script>
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
$(function() {
$("#totalCal").click(function(){
alert(JSON.stringify($('#product').serializeObject()));
return false;
});
});
</script>
You can use some custom code to format your array. Here is the simplest solution:
function getFormattedArray(array){
var result = [];
for(var currentPosition = 0;currentPosition < array.length; currentPosition += 3) {
result.push({ProductId: array[currentPosition].value,
qty: array[currentPosition+1].value,
total: array[currentPosition+1].value});
}
return result;
}

How to update parent table from partial view using Ajax

I have a table that lists the courses in the system with a Select button for each Course (in a row). When I click Select, the enrolled users of that course are displayed. The Course entity has navigation property public List<CourseRegistration> CourseRegistrations { get; set; }
I have this ViewModel for this purpose:
public class CourseIndexViewModel
{
public int SelectedCourseId { get; set; }
public List<Course> Courses { get; set; }
}
Just under the enrollments list (or registrations) I have a textbox (for keyword) and button to search users for enrollment. I use AJAX to execute an action of controller (UserController) (to which I pass the keyword) which searches users in the db, and passes the result set to a partial view, which returns a table of users with Enroll button in each row.
Everything works fine so far. Now, I need to implement the Enroll button inside the Partial View. However, I will need the id of the course, which is actually available in the main view (i.e., SelectedCourseId). Is there a way to access that value from the partial view? Do I have to (or should I) use hidden input for this purpose?
The biggest challenge is updating the enrollment list shown in the main View after enrolling a new user. I want to use Ajax to do that to prevent page refresh.
Is it feasible and recommended to use Ajax to get the enrollments again from the database and replace the existing enrollments table in the main view with the new table generated in the partial view?
UPDATE
Here is the main view:
#model EcholuMvc.Models.CourseIndexViewModel
<table class="table">
<tr>
<th></th>
<th>
CourseTitle
</th>
<th></th>
</tr>
#foreach (var item in Model.Courses)
{
<tr #(Model.SelectedCourseId == item.CourseId ? "style=background-color:whitesmoke;" : "style=" )>
<td>
#Html.ActionLink("Select", "Index", new { courseId = item.CourseId })
</td>
<td>
#Html.DisplayFor(modelItem => item.CourseTitle)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.CourseId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.CourseId })
</td>
</tr>
if (Model.SelectedCourseId == item.CourseId)
{
<tr>
<td>
<h4>Enrolled users:</h4>
<table class="table">
<tr>
<th>First name</th>
<th>Last name</th>
<th></th>
</tr>
#if (item.CourseRegistrations.Count > 0)
{
var registrations = item.CourseRegistrations;
foreach (var reg in registrations)
{
<tr>
<td>
#reg.Member.FirstName
</td>
<td>
#reg.Member.LastName
</td>
<td>
#Html.ActionLink("Delete", "Delete", new { memberid = reg.MemberId, courseid = reg.CourseId })
</td>
</tr>
}
}
else
{
<tr>
<td colspan="4">No enrollment!</td>
</tr>
}
</table>
<div class="container-fluid">
<div class="row">
<div class="col-sm-9">
<input id="txt_SearchUser" placeholder="Enter a name.." class="form-control " type="text" />
</div>
<input id="btn_SubmitUserSearch" class="btn btn-default btn-sm col-sm-3" type="button" value="Search" />
</div>
<div class="row">
<div id="div_UserSearchResults" class="col-sm-12">
</div>
</div>
</div>
<script>
$("#btn_SubmitUserSearch").click(function () {
$.ajax({
url: 'Account/SearchUsers',
contentType: 'application/html; charset=utf-8',
data: { keyword: $('#txt_SearchUser').val() },
type: 'GET',
dataType: 'html'
})
.success(function (result) {
$('#div_UserSearchResults').html(result);
})
.error(function (xhr, status) {
alert(status);
})
});
</script>
</td>
</tr>
}
}
</table>
And, here is the partial view:
#model IEnumerable<EcholuMvc.Models.ApplicationUser>
<table class="table-striped" >
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
<select id="drp_Role">
<option value="Student" selected="selected">Student</option>
<option value="Instructor">Instructor</option>
</select>
</td>
<td>
<input id="btn_Enroll" data-userid="#item.Id" type="button" />
</td>
</tr>
}
</table>
If you simply want the selected courseId in client side (for your ajax submit of new enrollment or any other thing), you may add a hidden field to the main view and read it from that when needed.
#Html.HiddenFor(s=>s.SelectedCourseId)
Now whenever you need it for your ajax posts, just read the value of this and use
var selectedCourseId=$("#s.SelectedCourseId").val();
But If you want the courseId in your search functionality for some reason, you may pass the selected courseId to your ajax call as a parameter. Keep the course id as the html 5 data attribute to your search input field
<input id="txt_SearchUser" placeholder="Enter a name.."
data-course="#item.CourseId" class="form-control " type="text" />
Now when you make the ajax call, read this value and send it.
$("#btn_SubmitUserSearch").click(function () {
$.ajax({
url: 'Account/SearchUsers',
data: { keyword: $('#txt_SearchUser').val(),
courseId:$('#txt_SearchUser').data("course") },
type: 'GET',
dataType: 'html'
})
.success(function (result) {
$('#div_UserSearchResults').html(result);
})
.error(function (xhr, status) {
alert(status);
})
});
Make sure your SearchUsers endpoint accept this new param and pass that to the resulting partial view it will render.
public ActionResult SearchUsers(string keyword,int courseId)
{
// to do : Do something with the passed values
// to do : return something
}
Also i assume that, with your if condition you are rendering only one search form in your page because you cannot have duplicate id's. Also consider using Url.Action helper method to generate the proper url to the action method instead of hardcoding the url as explained in this post.

Problem when trying to render a PartialView in ASP MVC 3

I have a problem now with ASP MVC 3 when trying to rend a that is stored in a PartialView after an AJAX Request is done. Here is the code of my two views:
#model ICollection<Foo.ViewModels.OrderSearchViewModel>
#using Foo.Helpers
#{
ViewBag.Title = "Sales Order Lookup";
}
#using (Ajax.BeginForm(new AjaxOptions()
{
HttpMethod = "GET",
UpdateTargetId = "results",
InsertionMode = InsertionMode.Replace
}))
{
#*"Search","OrderSearch",FormMethod.Get*#
<div id="Criteria" style="width: 800px;margin-left:10%">
<table id="tblSearchCriteria" class="FunnyRedLine" width="100%">
<!-- Many boring search fields here -->
<td style="width: 40%">
<input type="submit" value="Search" class="Text" />
</td>
</tr>
</table>
</div>
}
#Html.Partial("SearchResults",Model)
This is the partial view
#model ICollection<Foo.ViewModels.OrderSearchViewModel>
#using Foo.Helpers
#if (Model.Count > 0)
{
<div id="results" style="width: 800px; margin-left:10%">
<table id="tbl">
<tr>
<th>Sod Id</th>
<th>Sales Ref</th>
<th>SOP Ref</th>
<th>Order Date</th>
<th>Value</th>
<th>Status</th>
<th>Del Date</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td width="30" align="center">#Html.DisplayFor(modelItem => item.Id)</td>
<td width="30" align="center">#Html.DisplayFor(modelItem => item.SalesPersonRef)</td>
<td width="200" align="center">#Html.DisplayFor(modelItem => item.SOPRef)</td>
<td width="100" align="left">#Html.FormatDate(item.OrderDate)</td>
<td width="100" align="right">#Html.FormatNumber(item.Value,"C2")</td>
<td width="300" align="left">#Html.DisplayFor(modelItem => item.Status)</td>
<td width="100" align="left">#Html.FormatDate(item.DelDate)</td>
</tr>
}
</table>
</div>
}
And this is my controller
public class OrderSearchController : Controller
{
//
// GET: /OrderSearch/
[Ajax(false)]
public ActionResult Index()
{
var viewModel = new List<OrderSearchViewModel>();
ViewBag.SalesPeople = GetAllSalesPeople()
ViewBag.OrderTypes = GetAllOrderTypes()
return View(viewModel);
}
[Ajax(true)]
public ActionResult Index(string id, string startDate, string endDate, string postCode, string salesPersonId, string salesPersonRef,
string orderTypeId, string serialNo, string customerPO)
{
var service = new eSodSrv();
var viewModel = service.GetHeaders(id.ToInt32(), salesPersonId.ToInt32(), orderTypeId.ToInt32(), startDate.ToDate(), endDate.ToDate(), postCode, customerPO, serialNo, salesPersonRef);
return PartialView("SearchResults",viewModel);
}
}
The AJAX request is working, it is entering the correct method (Ajax is a custom attribute that checks Request.IsAjaxRequest()) and it is returning data, so why is the view not rendered?
The partial view is not appearing, because your target div is not being rendered. Instead of using #Html.Partial() in your main view, insert the following:
<div id="results" />
This will create the target, where your partial will be inserted.

Categories