How to pass the values from View to Controller using ajax method? - asp.net-mvc

I am developing MVC application.
I want pass the values from list to the controller,
The below code is to display the list of Products ...it shows perfectly.
#using (Html.BeginForm("Create", "Order", FormMethod.Post, new { enctype = "multipart/form-data", id = "frmCreate" }))
{
#Html.ValidationSummary(true)
<div class="row-fluid">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Section Name</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
#foreach (var item in ViewBag.ProductList)
{
<tr>
<td >#item.SectionName</td>
<td >#item.Quantity</td>
</tr>
}
</tbody>
</table>
<span class="span12 alert alert-success" id="status-message" style="margin-bottom:10px;"><strong>Your Order has been sent to HO sucessfully.</strong>Clcik Here to check status. Please click on back button to view list.</span>
}
Now, on when I click on the above link, I want to pass the data to the method in controller.
I have written the below code, It calls the method of controller but the list doesn't contain any items. It shows the null value. how to pass the list using ajax ?
Whats wrong in code ?
<script type="text/javascript">
$(document).ready(function () {
$('#CheckOrder').click(function(){
$.ajax({
url: '#Url.Action("DATACoME")' + '?List=#ViewBag.ProductList'
}).done(function(){
//do something
});
});
</script>

Try this:
<script type="text/javascript">
$(document).ready(function () {
$('#CheckOrder').click(function(){
$.ajax({
url: '#Url.Action("DATACoME")',
data: {parameterNameFromTheController: '#ViewBag.ProductList'}
}).done(function(){
//do something
});
});
</script>

Related

MVC Partial Page returns whole page, not just the partial

I have a button on a page:
<div>
From:
<input id="fromDate" type="date" name="fromDate" value="#a.FromDate">
To:
<input id="toDate" type="date" value="#a.ToDate">
<button type="button" id="btn_transactions" class="btn btn-primary" onclick="btnTrans()"><span class="glyphicon glyphicon-search"></span></button>
<label class="buy-heading">Total Buys: #String.Format("{0:n0}", #q.BuyQuantity)</label><label class="sell-heading">Total Sells: #String.Format("{0:n0}", #q.SellQuantity)</label>
</div>
It calls this function on click:
function btnTrans() {
var postdata = { "symbol": $("#savesymbol").val(), "fromDate": $("#fromDate").val(), toDate: $("#toDate").val() };
var url = "Company/Transactions?symbol=" + $("#savesymbol").val() + "&fromDate=" + $("#fromDate").val() + "&toDate=" + $("#toDate").val();
$.ajax({
url: url,
success: function (result) {
alert(result)
$('#transTarget').html(result);
},
error: function () {
//alert("Error occured");
}
});
}
The controller method is:
public async Task<PartialViewResult> Transactions(string symbol, string
fromDate, string toDate)
{
return PartialView("Transactions");
}
This is the partial view:
<table id="transactionsTable" class="table table-bordered display hover no-wrap dataTables" style="width: 100%">
<thead>
<tr>
<th>Account Category</th>
<th>Trade Date</th>
<th>Account Name</th>
<th>Activity</th>
<th>Quantity</th>
<th>Exec Price</th>
<th>Principal</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
var a = item.accounts;
foreach (var item2 in a)
{
<tr>
<td>#item2.AcctCategory</td>
<td>#String.Format("{0:MM/dd/yyyy}", #item2.TradeDate)</td>
<td>#item2.AccountName</td>
<td>#item2.Trans</td>
<td>#String.Format("{0:n}", item2.Quantity)</td>
<td>#String.Format("{0:n}", item2.ExecutionPrice)</td>
<td>#String.Format("{0:n}", item2.PrincipalAmount)</td>
</tr>
}
}
</tbody>
</table>
I have 3 partials on this page as follows:
<div class="mycontent2">
#{Html.RenderAction("Documents", "Company");}
</div>
<div class="mycontent2">
#{Html.RenderAction("Holdings", "Company");}
</div>
<div class="mycontent2">
#{Html.RenderAction("Transactions", "Company");}
</div>
The problem is that the partial view returned from the controller method returns the WHOLE page, not just the partial part of transactions. What am I doing wrong?
Return a model from the controller. Like this;
return PartialView("Transactions", model);
Do it for others partial.
Then, you will use model in your view.
Use #{ Layout = null; } in your partial view.

How to show partial view with parameter on click

I have a database with people and phones and i created a partial view that shows persons phones. I want this patial view to be loaded on click at some button like ShowPhones or something like that.
This is how i call view
#Html.Partial("ShowPersonsPhones", item.phones)
This is my partial view
#model IEnumerable<Project.Models.Phone>
<h2>Parial View</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Numer)
</th>
<th>
#Html.DisplayNameFor(model => model.Model)
</th>
</tr>
#foreach (var phone in Model)
{
<tr>
<td>
#Html.DisplayFor(item => phone.Numer)
</td>
<td>
#Html.DisplayFor(item => phone.Model)
</td>
</tr>
}
</table>
EDIT:
i tried to do some javascript in view but it just doesnt work
<style>
.shown{
display : inline;
}
.hidden{
display : none;
}
</style>
#Scripts.Render("~/bundles/jquery")
<script type="text/javascript">
function show_partial(i) {
alert("show partial " + i);
var divsname = '#partial' + i;
div = $(divsname);
if (div.hasClass('hidden'))
{
div.removeClass("shown");
div.addClass("hidden");
}
else
{
div.removeClass('hidden');
div.addClass("shown");
}
}
</script>
When i put alert in the function it shows but doesnt change classes for some reason.
In button click event, you can load the partial view.
ViewPage
<input type="button" id="btn" value="ClickMe" onclick="loadPartialView()" />
<div id="partialDiv"></div>
<script type="text/javascript">
function loadPartialView() {
$("#partialDiv").load('#Url.Action("IndexView","Home")');
}
</script>
In Controller, you can return the partial view with the parameter.
public ActionResult IndexView()
{
return PartialView("_PartialView", db.Phones.ToList());
}

How refresh a view in MVC

I have _LayoutOnecs.html file and View Loads with in it renderbody and displays list of records in table. in one of table column i have a Delete icon on click of it goes to controller and deletes record from database once the record is deleted the view should be refreshed so i returned the action to controller which fetches all the records
public ActionResult GetAdvertisementDetails()
{
var advertisementList = new AdvertisementManager().GetAdvertisementDetails();
return View("AdvertisementDetails", advertisementList);
}
public ActionResult DeleteAdvertisementDetails(int id)
{
new AdvertisementManager().DeleteAdvertisementDetails(id);
return RedirectToAction("GetAdvertisementDetails", "Advertisement");
}
once Delete is done it is going to GetAdvertisementcontroller and return view but the Deleted record sits there in table if i Refresh the page by pressing F5 the record is removed from table.
How do i Refresh automatically when the record is deleted
View Code
<div class="col-md-12 main_table">
<div class="table-responsive">
<table class="table" id="hom_table">
<tr>
<th>Advertisement Name</th>
<th>Link</th>
<th>Start Date</th>
<th>End Date</th>
<th width="100">Action</th>
</tr>
#foreach (var advertisements in Model)
{
<tr>
<td> #advertisements.Description</td>
<td> #advertisements.ImageUrl</td>
<td> #advertisements.StartDate</td>
<td> #advertisements.EndDate</td>
<td>
<a onclick="EditadvertisementDetails(#advertisements.AdvertisementId)">
<i class=" pull_Advt_details tbl_edit_btn fa fa-edit Editbutton"></i>
</a>
<a id="Deladvertisement" onclick="Deleteadvertisement(#advertisements.AdvertisementId)" >
<i class="tbl_del_btn fa fa-trash"></i>
</a>
</td>
</tr>
}
</table>
</div>
<!-- Responsive main table Ends -->
</div>
Ajax calls stay on the same page. Your use of return RedirectToAction("GetAdvertisementDetails", "Advertisement"); in the controller method is ignored. Its also unnecessary to redirect since you can just remove the row from the table
Modify the html to (note remove the id attribute which is generating invalid html):
<a class="delete" data-id="#advertisements.AdvertisementId>
<i class="tbl_del_btn fa fa-trash"></i>
</a>
and use the following script to call the controller method and remove the row
var url = '#Url.Action("DeleteAdvertisementDetails", "Advertisement")';
$('.delete').click(function() {
var row = $(this).closest('tr');
$.post(url, { id: $(this).data('id') }, function(response) {
if(response) {
row.remove();
}
}).fail(function (response) {
// display error message?
});
});
and modify the controller to
[HttpPost]
public JsonResult DeleteAdvertisementDetails(int id)
{
new AdvertisementManager().DeleteAdvertisementDetails(id);
return Json(true);
}

Connecting MVC Model View with associated Knockout.js ViewModel

Background: I'm pretty new to MVC & Knockout.js but I am trying to get up to speed on these technologies. I am using MVC 5 with EF6 and Knockout.JS 3.2.
I have a Detail view that pulls a "VoteAnswer" object using MVC based on the ID passed in the URL:
For example I can go to the url MyDomain/VoteAnswers/Details/1 and it will pull the information from my database correctly (It pulls a VoteAnswer with the ID of 1) and display in my Details view. However I am trying to hook-up my Knockout.js "VoteAnswer" ViewModel to function the same way and am having trouble.
Here is my Details View: (Note the #Html.DisplayFor(model => model.VoteAnswerId) etc works and displays the data from my Database.
#model AM_SPA_TestSite.Models.VoteAnswer
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Details</title>
<script src="~/KnockoutViewModels/VoteAnswers.js"></script>
</head>
<body>
<div>
<h4>VoteAnswer</h4>
<hr />
<table>
<tr>
<td>Id</td>
<td data-bind="text: id"></td>
</tr>
<tr>
<td>Display Text</td>
<td data-bind="text: isActive"></td>
</tr>
<tr>
<td>IsActive</td>
<td data-bind="text: displayText"></td>
</tr>
</table>
<table>
<tr>
<td>Id</td>
<td><input type="text" data-bind="value: id" /></td>
</tr>
<tr>
<td>Display Text</td>
<td><input type="text" data-bind="value: displayText" /></td>
</tr>
<tr>
<td>IsActive</td>
<td><input type="text" data-bind="value: isActive" /></td>
</tr>
</table>
<table>
<tr>
<td>Id</td>
<td>#Html.DisplayFor(model => model.VoteAnswerId)</td>
</tr>
<tr>
<td>Display Text</td>
<td>#Html.DisplayFor(model => model.DisplayText)</td>
</tr>
<tr>
<td>IsActive</td>
<td>#Html.DisplayFor(model => model.IsActive)</td>
</tr>
</table>
</div>
Here is my Knockout.Js ViewModel
// VoteAnswer ViewModel
var VoteAnswerVM = {
id: ko.observable(),
displayText: ko.observable(),
isActive: ko.observable(),
SaveVoteAnswer: function () {
$.ajax({
url: '/VoteAnswers/Create',
type: 'post',
dataType: 'json',
data: ko.toJSON(this),
contentType: 'application/json',
success: function (result) {
},
error: function (err) {
if (err.responseText == "Creation Failed")
{ window.location.href = '/VoteAnswers/Index/'; }
else {
alert("Status:" + err.responseText);
window.location.href = '/VoteAnswers/Index/';;
}
},
complete: function () {
window.location.href = '/VoteAnswers/Index/';
}
});
}
};
//Go
$(document).ready(function () {
//initialize and create new VoteAnswerVM by URL value here?
ko.applyBindings(VoteAnswerVM);
});
I know what I am missing is initializing the ViewModel with the ID of 1, but I was thinking the MVC model already has the data and the knockout.js SHOULD map to that data without manually initializing by sending a request to the database again. What am I missing? thanks.
EDIT: Added solution below. I'm not sure I am settled on this approach but here it is. Updated the controller to ONLY return a view and not query the DB. (otherwise I would have two database calls for the same data.
// GET: VoteAnswers/Details/5
public ViewResult Details(int? id)
{
return View();
}
Added an API Controller that does query the DB.
// GET: api/VoteAnswers/5
[ResponseType(typeof(VoteAnswer))]
public async Task<IHttpActionResult> GetVoteAnswer(int id)
{
VoteAnswer voteAnswer = await db.VoteAnswers.FindAsync(id);
if (voteAnswer == null)
{
return NotFound();
}
return Ok(voteAnswer);
}
In my View (.cshtml file) I reference my knockout.js ModelView, View is Below:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Details</title>
<script src="~/KnockoutViewModels/VoteAnswers.js"></script>
</head>
<body>
<div>
<h4>VoteAnswer</h4>
<hr />
<table>
<tr>
<td>Id</td>
<td data-bind="text: VoteAnswerId"></td>
</tr>
<tr>
<td>Display Text</td>
<td data-bind="text: IsActive"></td>
</tr>
<tr>
<td>IsActive</td>
<td data-bind="text: DisplayText"></td>
</tr>
</table>
<table>
<tr>
<td>Id</td>
<td><input type="text" data-bind="value: VoteAnswerId" /></td>
</tr>
<tr>
<td>Display Text</td>
<td><input type="text" data-bind="value: DisplayText" /></td>
</tr>
<tr>
<td>IsActive</td>
<td><input type="text" data-bind="value: IsActive" /></td>
</tr>
</table>
</div>
<div id="error"></div>
</body>
</html>
Updated My ViewModel script to access the Database based on the URL ID.
// VoteAnswer ViewModel
var VoteAnswer = function () {
var self = this;
self.VoteAnswerId = ko.observable();
self.DisplayText = ko.observable();
self.IsActive = ko.observable();
self.SaveVoteAnswer = function () {
$.ajax({
url: '/VoteAnswers/Create',
type: 'post',
dataType: 'json',
data: ko.toJSON(this),
contentType: 'application/json',
success: function (result) {
},
error: function (err) {
if (err.responseText == "Creation Failed")
{ window.location.href = '/VoteAnswers/Index/'; }
else {
alert("Status:" + err.responseText);
window.location.href = '/VoteAnswers/Index/';;
}
},
complete: function () {
window.location.href = '/VoteAnswers/Index/';
}
});
}
self.load = function (id) {
if (id != 0) {
$.ajax({
url: '/api/VoteAnswers/' + id,
type: 'get',
data: ko.toJSON(this),
contentType: 'application/json',
success: function(data) {
self.VoteAnswerId = ko.observable(data.voteAnswerId);
self.DisplayText = ko.observable(data.displayText);
self.IsActive = ko.observable(data.isActive);
ko.applyBindings(self);
},
error: function(err) {
if (err.responseText == "Creation Failed") {
window.location.href = '/VoteAnswers/Index/';
} else {
$("#error").text("Status:" + err.responseText);
//window.location.href = '/VoteAnswers/Index/';;
}
},
complete: function() {
//window.location.href = '/VoteAnswers/Index/';
}
});
} else {
window.location.href = '/VoteAnswers/Index/';
}
}
};
function GetURLParameter() {
var sPageUrl = window.location.href;
var indexOfLastSlash = sPageUrl.lastIndexOf("/");
if (indexOfLastSlash > 0 && sPageUrl.length - 1 != indexOfLastSlash)
return sPageUrl.substring(indexOfLastSlash + 1);
else
return 0;
}
//Go
$(document).ready(function () {
//initialize and create new VoteAnswerVM by URL value here?
var viewModel = new VoteAnswer();
viewModel.load(GetURLParameter());
});
I hope I understood you correctly, if my answer is all wrong for your question let me know where I went wrong.
First thing to realize is, if you bind a KO observable to an input field, knockout will not look at the initial value of that input field and store it in the observable. It will do the opposite: it will look at the current value in the observable and store it in the input field's value. In your case, the observable are initialized without a value, which in JavaScript means the value undefined. So if you bind your observables to the fields you've filled with Razor/MVC viewmodel, you'll immediatly overwrite those values with the empty values stored in your observables.
There IS a way to fill your Knockout model with your data through Razor, but it involves inline JavaScript and is a bad practise for a number of reasons (I will elaborate on this on request).
The best way to do this is to separate your views from your data: Don't inject the MVC viewmodel into the view, but make a separate endpoint that returns JSON and return the data there (this endpoint will receive the ID parameter instead of the view). The JSON endpoint is called from JavaScript and can be used to fill your model with the correct values.
Upsides: separation of concerns, possibility to enable view caching for a more responsive frontend, no need to use razor syntax, or even worse, combine it with inline JS. All your binding of data to the UI will happen through Knockout. I learned this myself because we also started out using razor, but on the long run this solution wasn't feasible for a big project. We never regretted the switch to always getting the data from separate JSON endpoints.
If you are unsure on how to do this I can write some pseudocode to illustrate the idea.
These may be the possible solutions
1.) data_bind is wrongly used
<td><input type="text" data-bind="value: isActive" /></td> // which is wrong
<td><input type="text" data_bind="value: isActive" /></td> //data_bind is wrongly used
2.)
If still problem exists you may try this syntax
#Html.DisplayFor(model => model.IsActive, new { data_bind = "value:IsActive" });
If you find still something missing please provide some detail info .

How to reset the partial view containing cascading dropdown list in MVC4 Jquery

I am using MVC4/EF and I have four cascading dropdownlist and I got it working the first time. So when the page is rendered first time, I am able to select the first dropdown and filter the result on the second and by selecting second dropdowm the third dropdwon is filtered and fourth and based on the fourth drop down I populate a edit view. But when I go back and change the selection in the first drop down, it is filtering the second drop down but not resetting the third, fourth dropdwon list and the edit partial view. Here is teh first dropdwon partial view code.
CampusUsercontrol.cshtml
#model RHMS.Models.RoomEditor
#using (Ajax.BeginForm("SelectCampus", "RoomEditor", new AjaxOptions { UpdateTargetId = "Buildings" }))
{
#Html.DropDownListFor(
m => m.SelectedCampusID,
new SelectList(Model.Campuses,"CampusId", "Name"),
string.Empty
)
}
<script type="text/javascript">
$('#SelectedCampusID').change(function () {
$(this).parents('form').submit();
});
</script>
Index.cshtml
#model RHMS.Models.RoomEditor
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<table cellpadding="0" cellspacing="4" border="0">
<tr>
<td>Campus </td>
<td> :</td>
<td>#Html.Partial("CampusUserControl", Model)</td>
</tr>
<tr>
<td>Building </td>
<td> :</td>
<td><div id="Buildings">#Html.Partial("BuildingUserControl", Model)</div></td>
</tr>
<tr>
<td>Floor </td>
<td> :</td>
<td><div id="Floor">#Html.Partial("FloorsUserControl", Model)</div></td>
</tr>
<tr>
<td>Room </td>
<td> :</td>
<td><div id="Room">#Html.Partial("RoomUserControl", Model)</div></td>
</tr>
</table>
<div id="RoomInfo">
#Html.Partial("RoomInfoUserControl", Model)
</div>
Please help me how to refresh the other partial views when the first one is changed.
Looks like this part of your javascript code is beeing executed only on the first load of the page
<script type="text/javascript">
$('#SelectedCampusID').change(function () {
$(this).parents('form').submit();
});
</script>
try wiring the change event for #SelectedCampusID using Jquery's on binding. You might also have to do the same for the other dropdowns.

Resources