MVC Partial view nor returning data - c#

I'm trying to do what I believe is simple operation/request.
I have a html input text in a view and with Ajax I call the controller to return a partial view with the result of a SQL query with a where clause that comes from the text input, the goal is to retrieve a table with the info.
Below you have the code:
AJAX request from the view to call the controller:
$(function()
{
$.ajax
({
type: "POST",
url: '#Url.Action("result","result")',
data: { Code: result},
success: function(data) {},
error: function(){
alert("error");
}
});
});
Partial view where I receive the model's information but when loaded in the view it does not change, there are no results:
#model xpto.Models.result
#if (Model != null)
{
<h1>Title</h1>
<table>
<tr>
<td>
#Model.Code
</td>
<td>
</td>
</tr>
</table>
}
else
{
<table>
<tr>
<td>
<p>No results</p>
</td>
</tr>
</table>
}
Controller:
Only with the HttpPost to return the Partial View
[HttpPost]
public ActionResult TableStocks(TableStocks model)
{
if (ModelState.IsValid)
{
SqlConnection conn = new SqlConnection(ConnStr);
SqlCommand selectX = new SqlCommand("sqlquery #param"), conn);
SqlDataReader reader;
selectX.Parameters.AddWithValue("#param", model.code);
connection.Open();
reader = selectX.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
model.Code = Int32.Parse(reader["code"].ToString());
}
}
else
{
Console.Write("ERROR");
}
}
return PartialView("result", model);
}
View stays with no results even after the controller receive the value from the input text and retrieve the model with the info from the database.
#Html.Partial("result", Model)

I assume you have verified that the partial view gets the model correctly. If so, then what is left is to modify your AJAX call to replace the partial on the page as such:
$(function()
{
$.ajax
({
type: "POST",
url: '#Url.Action("result","result")',
data: { Code: result},
success: function(data) {
$('#myDiv').html(data); //Add this line to set the data into the page
},
error: function(){
alert("error");
}
});
});

Related

Bind a list with jquery datatable

I have made an MVC application which would display a set of file names located in a given directory. To display the list, i have used normal table in my view.Since the view returns a huge list of file names, i am asked to use jquery datatable,which i dont have much idea about. I tried by going through lot of suggestions but could not return the list at all. Please have a look at the code below.
Controller:
public class SupportingChannelController : Controller
{
// GET: SupportingChannel
List<SupportingChannel> _list = null;
SupportingChannelBL _bl = new SupportingChannelBL();
SupportingChannelDataVM _data = new SupportingChannelDataVM();
public ActionResult GetSupportingChannelData()
{
_list = _bl.channel();
_data._model = _list;
return View("SupportingChannel", _data);
}
View
#model MultiRequestInterface.Models.SupportingChannelDataVM
#{
ViewBag.Title = "SupportingChannel";
}
<h2>Supporting Channels</h2>
#using (Html.BeginForm("getComType","SupportingChannel",FormMethod.Post))
{
<div>
<style>
table,th,td
{
border: 1px solid black;
border-collapse: collapse;
align-content:center;
}
</style>
<div style="border:solid;width:100%;overflow-x:auto;">
<table id="table" align="center" style="width:100%" class="display">
<thead>
<tr>
<th>Communication Type</th>
<th>Communication Description</th>
</tr>
</thead>
</table>
</div>
<input type="submit" name="submit" value="submit" />
</div>
if (TempData["testmsg"] != null)
{
<script type="text/javascript">
alert("#TempData["testmsg"]");
</script>
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script
src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js">
</script>
<script type="text/javascript">
$(document).ready(function ()
{
var table = $('#table').DataTable();
var data = table.data;
$.ajax({
url: 'GetSupportingChannelData/SupportingChannel',
dataType: 'json',
contentType: "application/json;",
data: JSON.stringify(data),
success: function () {
},
});
});
</script>
Since i am returning a list to the view, i just want some help as in howcan i pass this list as data to the jquery datatable..
Thanks in advance
Since you've already created HTML table containing column headers, just use built-in AJAX call function in DataTable to fetch data as JSON:
$('#table').DataTable({
"ajax": {
"url": "#Url.Action("GetSupportingChannelData", "SupportingChannel")", // action method URL
"type": "GET",
"datatype": "json"
},
, columns: [
{ data: 'columnName1' },
{ data: 'columnName2' },
{ data: 'columnName3' },
{ data: 'columnName4' },
{ data: 'columnName5' }
],
// other settings
});
Then use return type JsonResult to return your list of model as JSON data that will passed to DataTable (I assumed there is another action method which returns view where DataTable should belongs to):
public class SupportingChannelController : Controller
{
List<SupportingChannel> _list = null;
SupportingChannelBL _bl = new SupportingChannelBL();
// other class-level fields
// returns view to render DataTable
public ActionResult GetChannelData()
{
return View();
}
// returns JSON data from list of model values
public ActionResult GetSupportingChannelData()
{
// other stuff
_list = _bl.channel();
// other stuff
return Json(new { data = _list }, JsonRequestBehavior.AllowGet);
}
}
Additional references:
Implement jQuery Datatable in ASP.NET MVC application
AJAX CRUD Operation With jQuery DataTables In ASP.NET MVC 5

Can't access to action method from JQuery if [AntiForgeryToken] is enabled

I have a JQuery function that works ok but if I enable [AntiForgerToken] on the Action Method the JQuery function can't access the Action Method, on the view I have other snippet where I enabled AntiForgeryToken:
#using (Html.BeginForm("InsertStudent","Students",FormMethod.Post, new { #id="myform"}))
{
#Html.AntiForgeryToken()
It doesn't matter if the #Html.AntiForgeryToken() inside the view is enabled or not, the JQuery function works good, the one with the problem is at the Action Method...
Why is happening that? What I'm missing?? I've read is very important for security to have [AntiForgeryToken] enabled on the Post Action Methods so I think that the application should work with it enabled in both places the Action Method and the View.
JQuery function:
function InsertShowStudents() {
var counter = 0;
$.ajax({
type:"post",
url: "/Students/InsertStudent/",
data: { Name: $("#Name").val(), LastName: $("#LastName").val(), Age: $("#Age").val() }
}).done(function (result) {
if (counter==0) {
GetStudents();
CounterStudents();
counter = 1;
}
else {
$("#tableJQuery").append("<tr>"+"<td>"+result.Name+"</td>"+"<td>"+result.LastName+"</td>"+"<td>"+result.Age+"</td>"+"</tr>")
}
//clear the form
$("#myform")[0].reset();
}).error(function () {
$("#divGetStudents").html("An error occurred")
})
}
Action method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult InsertStudent(Student student)
{
if (ModelState.IsValid)
{
db.Students.Add(student);
db.SaveChanges();
//ModelState.Clear();
return RedirectToAction("InsertStudent");
}
return View(student);
}
columns of the table:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Age)
</td>
#* <td style="display:none" class="tdStudentID">#Html.DisplayFor(modelItem => item.StudentID)</td> *#
<td>
<img src="~/images/deleteIcon.png" width="20" height="20" class="imgJQuery" data-id="#item.StudentID" />
</td>
<td>
#Html.ActionLink("Details","Details", new { id=item.StudentID})
</td>
</tr>
}
You not passing the value of the token in your ajax call so an exception is thrown. You can get the value of the token using
var token = $('[name=__RequestVerificationToken]').val();
and modify your ajax call to include it using
data: { __RequestVerificationToken: token, Name: $("#Name").val(), LastName: $("#LastName").val(), Age: $("#Age").val() }
however, it is easier to just serialize your form which will include the token
$.ajax({
type:"post",
url: '#Url.Action("InsertStudent", "Students")', // don't hardcode your url's
data: $('#myform').serialize(),
}).done(function (result) {
Side note: Ajax calls never redirect (the whole point of ajax is to stay on the same page) so having return RedirectToAction("InsertStudent"); in your InsertStudent() will not work. In addition, your returning html, so the $("#tableJQuery").append() code in the .done() callback will fail.
It appears you have a form to add a new Student so your method simply need to return a JsonResult indicating success or otherwise, and if successful, then you can add a new row to your table based on the values in the form, for example
}).done(function (result) {
if (result) {
var row = $('<tr></tr>');
row.append($('<td></td>').text($("#Name").val()));
... // add other cells
$("#tableJQuery").append(row);
//clear the form
$("#myform")[0].reset();
} else {
// Oops something went wrong
}
})

What is the most likely cause of the 500 error here?

I will show you all the moving parts involved.
View:
#{
ViewBag.Title = "Partners";
}
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<h1>Partners</h1>
<p>Click to see survey answers or delete partner</p>
<table class="table">
<thead>
<tr>
<th>Partner Name</th><th>Actions</th>
</tr>
</thead>
<tbody>
#foreach ( var NameIdPair in ViewBag.PartnersAndIds )
{
<tr>
<td>
#NameIdPair.Name
</td>
<td>
<button class="btn btn-info view-partner-surveys" data-partnerid="#NameIdPair.Id">View Survey Answers</button>
<button class="btn btn-warning delete-partner" data-partnerid="#NameIdPair.Id">Delete Partner</button>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
#section bottommost {
<script type="text/javascript">
$('.delete-partner').click(function () {
var row = $(this).closest('tr');
$.ajax({
method: 'POST',
url: 'DeletePartner',
data: { pid: $(this).attr('data-partnerid') },
dataType: 'json',
processData: false,
beforeSend: function () {
row.addClass('processing');
},
success: function (retinfo) {
if (retinfo.DeletedSuccessfully) { row.remove(); }
else { alert("Error .."); row.removeClass('processing'); }
},
error: function () { alert("Error"); row.removeClass('processing'); }
});
});
</script>
}
The problem is occuring with the AJAX call invoked with $('.delete-partner').click. The controller handling the request is the simple
[HttpPost]
public ActionResult DeletePartner ( int pid )
{
return Json(new { DeletedSuccessfully = this._Db.DeletePartner(pid) });
}
which used the method DeletePartner in a model defined by
public bool DeletePartner ( int id )
{
SqlCommand cmd = new SqlCommand("DeletePartner", this._Conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#id", id);
this._Conn.Open();
bool succeeded = cmd.ExecuteNonQuery() == 1 ? true : false;
this._Conn.Close();
return succeeded;
}
The sproc its calling is the simple
CREATE PROCEDURE DeletePartner
#id INT
AS
DELETE FROM Partners WHERE id=#id
Any idea where I'm going wrong here?
You should use the url of your ajax call like following.
url: '#Url.Action("DeletePartner")'
You have to give ajax url in the format like
url : '../controllerName/ActionName'
[HttpPost]
public ActionResult DeletePartner ( int pid )
{
return Json(new { DeletedSuccessfully = this._Db.DeletePartner(pid) });
}
The DeletedSuccessfully variable is not recognised by the controller. So it may cause 500 error

Login controller redirecting does not show page

I have a log in controller and a view. Whenever I click the log in button I check if the password given is correct and I used Redirect To Action to redirect to my home page. But, whenever I get to that page the page is not showing. What am I doing wrong???
In firebug it shows
GET http://localhost:64703/Home Page
should it be POST?
Javascript:
$('#Login').on('click', function () {
var model = {};
model["model.Password"] = $('#Password').val();
$.ajax({
url: '#Url.Action("Login", "LogIn")',
type: "POST",
data: model,
success: function (response) {
},
error: function (response) {
}
});
});
View:
<div >
<div >
#Html.ValidationSummary(true)
<table style="margin-top: 10px;">
<tr>
<td >
#Html.LabelFor(model => model.Password)
</td>
<td >
#Html.PasswordFor(model => model.Password)
</td>
</tr>
<tr>
<td colspan="2">
<label id="errorMsg" class="calibri">
</label>
</td>
</tr>
</table>
<input type="button" id="Login" value="Login" />
</div>
</div>
Controller:
[HttpPost]
public ActionResult Login(LogIn model)
{
try
{
EntityConnection connection = connect.getConnection();
Entities ctx = new Models.Entities(connection);
connection.Open();
connection.Close();
return RedirectToAction("Index", "HomePage");
}
catch (Exception ex)
{
return Json(ex);
}
}
Here is my Code.. Please let me know what should be done and what should not be done. Thanks in advance.
Change only your jquery code, redirect the page:
success: function (response) {
alert("if this test dialog appears, so page will redirect");
//just add this line:
window.location.href = '#Url.Action("Index", "HomePage")';
},
I think, on basis what you have posted, that there is either not a Controller or Action which matches:
Controller: HomePage
Action: Index
See the explanation of the RedirectToAction method.
You are using ajax to make the login request.
As such, you need to update your ajax response handlers to allow the page to redirect.
$('#Login').on('click', function () {
var model = {};
model["model.Password"] = $('#Password').val();
$.ajax({
url: '#Url.Action("Login", "LogIn")',
type: "POST",
data: model,
success: function (response) {
// Check for login is successful
if (response.LoginResult == true) window.location = response.Redirect;
else alert("Login failed.");
},
error: function (response) {
}
});
});
// Controller
[HttpPost]
public ActionResult Login(LogIn model)
{
try
{
EntityConnection connection = connect.getConnection();
Entities ctx = new Models.Entities(connection);
connection.Open();
connection.Close();
if (true) // Logic to validate login
{
return Json(new { LoginResult = true, Redirect = RedirectToAction("Index", "HomePage") });
}
return Json(new { LoginResult = false });
}
catch (Exception ex)
{
return Json(ex);
}
}
The above sample fuzzies over the login logic - so use whatever logic you currently have.
The core concept is that the controller should return a json object that the client can evaluate and determine what to do. Be aware that the success function will be triggered even if your login logic is incorrect - as long as there was no error by the server.

Pass ID in Html.ActionLink via ajax to get partial view

I have an MVC View page, strongly-typed to an enumerated product list. Each list item has an Html.ActionLink with a unique id. In my jquery file, I have an $.ajax function which should process the link with the corresponding id . The intent is to load a partial view on the same page, with that item's information, to allow editing for whatever item has been clicked. I don't want the actionr to result in a separate page, or generate a post to the server.
// here is the MVC stuff
#model IEnumerable<SimpleAjax.Models.Product>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.ActionLink("Edit", "ShowEdit", "Home", new { id=item.Id } ,new { id = "btnShowEdit" + item.Id, #class= ".button_action"})
|
</td>
</tr>
}
<div id="showEditProd">
</div>
//inside controller
public ActionResult ShowEdit(int id)
{
Product prod = db.Product.Find(id);
ProductViewModel viewModel = new ProductViewModel
{
EditProduct = prod
};
return PartialView(viewModel);
}
//inside a separate partial view page
#model SimpleAjax.Models.ProductViewModel
#using (Html.BeginForm("Index_AddItem", "Home", FormMethod.Post, new { id = "fid" }))
{
<div>
#Html.LabelFor(model => model.EditProduct.Name)
#Html.EditorFor(model => model.EditProduct.Name)
</div>
<div>
#Html.LabelFor(model => model.EditProduct.Price)
#Html.EditorFor(model => model.EditProduct.Price)
</div>
<div>
<input type="submit" value="Submit" />
</div>
}
now below works as expected, when I have hardcoded IDs:
$('#btnShowEdit1,#btnShowEdit2,#btnShowEdit3').click(function () {
$.ajax({
url: this.href,
contentType: 'application/html; charset=utf-8',
type: 'GET',
success: function (result) {
$('#showEditProd').html(result);
}
});
return false;
});
The above jquery works as desired. The partial view gets loaded on the same page as enumerated list. But obviously I don't want to hardcode variables. I may have x number of #btnShowEdit. I want to utilize a class, correct? So I have ".button_action" class that will enumerate the Id. But when I do that, as below, the link navigates to a separate page.
these go to a separate page, not what I want
$('.button_action').click(function (index) {
$.ajax({
url: this.href,
contentType: 'application/html; charset=utf-8',
type: 'GET',
success: function (result) {
$('#showEditProd').html(result);
}
});
return false;
});
});
//also tried this...
$('.button_action').each(function (index) {
$('#btnShowEdit' + index).click(function () {
$.ajax({
url: this.href,
contentType: 'application/html; charset=utf-8',
type: 'GET',
success: function (result) {
$('#showEditProd').html(result);
}
});
return false;
});
});
I know there's gotta be a simple solution.Thanks for your help in advance.
Any specific reason for not using the Ajax HTML-helper?
http://msdn.microsoft.com/en-us/library/system.web.mvc.ajax.ajaxextensions.actionlink(v=vs.108).aspx
You can use it as an actionlink, but it is done async and the result can be placed in your showEditProd.
#Ajax.ActionLink("Action",
"Controller",
_YOURID_,
new AjaxOptions { HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "showEditProd",
OnComplete = "your_js_function();" })
In case anyone else needs the solution to the above... It was too simple to believe.The jquery ajax code does not need an id htmlattribute from the Html.ActionLink. In fact, this extra attribute is what was causing the trouble. The jquery ajax recognizes the id from the "this.href' as that is the route controller along with the id parameter. Therefore I removed the id from htmlattributes in the actionlink. Now it's working as expected.
#Html.ActionLink("Edit", "ShowEdit", "Home", new { id=item.Id } ,new { #class= ".button_action"})
in js file
$('.button_action').click(function (index) {
$.ajax({
url: this.href,
contentType: 'application/html; charset=utf-8',
type: 'GET',
success: function (result) {
$('#showEditProd').html(result);
}
});
return false;
});
});
Check this:
$('.button_action').click(function (e) {
e.preventDefault() // this prevent default behavior for hyperlink on 'click' event

Categories