How to create partial view via AJAX call - javascript

I am in learning phase and I want to create partial view from Ajax call. But for every click the page gets redirected to a altogether New Page. Below is my attempt.
Link I referred from Stack Overflow SO LINK
Model
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
Home Controller:
public ActionResult PartialViewContainer()
{
return View();
}
public PartialViewResult All()
{
var students = _context.Students.ToList();
return PartialView("_Student", students);
}
public PartialViewResult Top3()
{
var students = _context.Students.OrderByDescending(s => s.Age).Take(3);
return PartialView("_Student", students);
}
public PartialViewResult Bottom3()
{
var students = _context.Students.OrderBy(s => s.Age).Take(3);
return PartialView("_Student", students);
}
Main View located inside Home Folder
#{
ViewBag.Title = "PartialViewContainer";
}
<div style="font-family: Arial">
<h2>Students</h2>
#Html.ActionLink("All", "All", new AjaxOptions {
HttpMethod = "GET",
UpdateTargetId = "divStudents",
InsertionMode = InsertionMode.Replace
})
<span style="color:Blue">|</span>
#Html.ActionLink("Top3", "Top3", new AjaxOptions{
HttpMethod = "GET",
UpdateTargetId = "divStudents",
InsertionMode = InsertionMode.Replace
})
<span style="color:Blue">|</span>
#Html.ActionLink("Bottom", "Bottom3", new AjaxOptions{
HttpMethod = "GET",
UpdateTargetId = "divStudents",
InsertionMode = InsertionMode.Replace
})
<div id="divStudents"></div>
</div>
"_Student" Partial view located inside "Shared" folder
#model IEnumerable<WebApplication3.Models.Student>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table" style="border: 1px solid black; background-color: silver">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Age)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Age)
</td>
</tr>
}
</table>
Initial page:
After Ajax Call
P.S: I have included jquery plug in.
But I could not find jquery.unobstrusice-ajax.js in my ASP.Net MVC
5 project template, so I have not included it.
Please guide me what am I doing wrong here.
EDIT 1
Replaced #html.ActionLink with #Ajax.ActionLink, but still it's
getting redirected to a new page.

try this:
Replace #html.ActionLink with #Ajax.ActionLink
#Ajax.ActionLink("All", "All", new AjaxOptions {
HttpMethod = "GET",
UpdateTargetId = "divStudents",
InsertionMode = InsertionMode.Replace
})

Keep in mind. AJAX CANNOT change the page.
I personally steered away from the unobtrusive ajax framwork. I just used good ole AJAX
What is happening is that ajax is not actually working and it is actually just doing an html GET.
Invoke a function like this when you press a button. This is how I solved the similar problem that I had.
This code may not be a direct cut and paste, but it is pretty close.
function CallAjax(actionPath) {
$.ajax({
url: actionPath,
type: 'POST',
success: function (partialView) {
$("#sampleContainer").html(partialView);
},
error: function () {
alert('error');
}
});
}

Related

When rendering my partial view it is not set it an instance of an object

I am attempting to use partial views for the first time and I need some help. I am posting a string from Javascript to my ASP controller so that I can query my database using that string. Like so:
JavaScript
function findEmployees(userCounty) {
$.ajax({
type: "POST",
url: '#Url.Action("Index", "Contact")',
data: JSON.stringify(userCounty),
contentType: "application/json",
error: function (e) {
console.log(e)
console.log("error")
}
});
}
Controller
[HttpPost]
public ActionResult Index([FromBody]string userCounty)
{
string county = userCounty.Substring(0, userCounty.IndexOf(" "));
var query = from SOP in _context.SalesOffice_Plant
where SOP.County == county
select new SalesOffice_Plant
{
Employee = SOP.Employee
};
return PartialView(query.ToList());
}
[HttpGet]
public ActionResult Index()
{
ViewData["Title"] = "Contact Us";
ViewBag.Current = "Contact";
return View();
}
When I set break points - I can see that the string is passed correctly and my LINQ query works just fine. My problem occurs when I want to render a table of the employees in my Index page. The JavaScript returns a value to the controller after the page loads. This means I needed a way to "refresh the page". I was told to use a partial view to solve this problem and this is what I came up with.
Index.cshtml
#model IEnumerable<Project.Models.SalesOffice_Plant>
//A bunch of Html
#await Html.PartialAsync("_IndexPartial")
//More Html
_IndexPartial.cshtml
#model IEnumerable<Project.Models.SalesOffice_Plant>
<table class="table">
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Employee)
</td>
</tr>
}
</tbody>
Ideally, I would like a table of Employees to be generated and displayed in the Index.cshtml. However, when I load the page I get and error telling me that my #await Html.PartialAsync("_IndexPartial") 'is not set to an instance of an object.
Any pointers in the right direction would be very helpful.
When you use ajax,it would not reload your page after backend code finishing,so you need to use .html() method to render the backend result to html.
Here is a whole working demo:
Model:
public class SalesOffice_Plant
{
public int Id { get; set; }
public string County { get; set; }
public string Employee { get; set; }
}
View(Index.cshtml):
<button type="button" onclick="findEmployees('a ')">Find</button>
<div id="employee">
</div>
#section Scripts
{
<script>
function findEmployees(userCounty) {
$.ajax({
type: "POST",
url: '#Url.Action("Index", "Contact")',
data: JSON.stringify(userCounty),
contentType: "application/json",
error: function (e) {
console.log(e)
console.log("error")
},
success: function (res) {
$("#employee").html(res); //add this...
}
});
}
</script>
}
Partial View(_IndexPartial.cshtml):
#model IEnumerable<SalesOffice_Plant>
<table class="table">
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Employee)
</td>
</tr>
}
</tbody>
</table>
Controller:
[HttpPost]
public ActionResult Index([FromBody] string userCounty)
{
string county = userCounty.Substring(0, userCounty.IndexOf(" "));
var query = from SOP in _context.SalesOffice_Plant
where SOP.County == county
select new SalesOffice_Plant
{
Employee = SOP.Employee
};
return PartialView("_IndexPartial", query.ToList()); //must specify the partial view name
//otherwise it will match the action name as partial view name
}
[HttpGet]
public ActionResult Index()
{
ViewData["Title"] = "Contact Us";
ViewBag.Current = "Contact";
return View();
}
Result:

Object Moved Here - RedirectToAction

Again, after tiresome attempts to solve this annoying issue, I am back here. I am experiencing an "Object moved here" on my view in my MVC5 application after some return RedirectToAction("Index", "Roles", model); action on my controller.
I have considered solutions from the following links:
RedirectToAction and "Object moved to here" error
ASP.NET MVC Website: Object Moved to Here
https://forums.asp.net/t/1643235.aspx?+Object+moved+to+here+problem
but none are applicable to my problem.
Before anyone marks this as a duplicate, please consider the scenario below:
But now the weird thing is that after I have clicked on the 'here' link and it now renders my view - it has a horizontal split screen showing the correct display of my view on top and below the view that throws an Http Error Code - in this case its Error Code 500 : Internal Server Error.
The reason why I am getting the http status code error is due to this unanswered question here (one of many) :
Failed to load resource: Uncaught TypeError: $(...).select2 is not a function
But that is besides the point right now.
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Name,Description")] ApplicationRole model)
{
try
{
if (ModelState.IsValid)
{
var role = new ApplicationRole()
{
Name = model.Name,
Description = model.Description
};
var roleManager = new RoleManager<ApplicationRole>(new RoleStore<ApplicationRole>(db));
var result = await roleManager.CreateAsync(role);
if (result.Succeeded)
{
return RedirectToAction("Index", "Roles", model);
}
else
{
AddErrors(result);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
// If we got this far, something failed, redisplay form
return View(model);
}
//Below is my index method in my Roles controller which is the action that redirection needs to route to:
[Route("/Roles")]
public ActionResult Index()
{
if (TempData["StatusMessage"] != null)
{
ViewBag.StatusMessage = TempData["StatusMessage"].ToString();
}
else
{
ViewBag.StatusMessage = "";
}
var roles = db.Roles.ToList();
return View("Index", roles);
}
//GET method to create view
public ActionResult Create()
{
return View();
}
View:
#model IEnumerable<User_Manager_Interface.Models.ApplicationRole>
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#if (ViewBag.StatusMessage != null)
{
if (ViewBag.StatusMessage != "")
{
string tmp = ViewBag.StatusMessage;
if (tmp.Contains("error"))
{
<div class="notification msgerror">
<a class="close"></a>
<p>#ViewBag.StatusMessage</p>
</div>
}
else
{
<div class="notification msgsuccess">
<a class="close"></a>
<p>#ViewBag.StatusMessage</p>
</div>
}
}
}
<br />
#Html.ActionLink("Create New", "Create", "Roles", new object { }, new { #class = "stdbtn" })
<br />
<br />
<div class="contenttitle radiusbottom0">
<h2 class="table"><span>Roles</span></h2>
</div>
<table cellpadding="0" cellspacing="0" border="0" class="stdtable" id="dyntable">
<colgroup>
<col class="con0" />
<col class="con1" />
<col class="con0" />
</colgroup>
<thead>
<tr>
<th class="head1">Name</th>
<th class="head0">Description</th>
<th class="head1">Options</th>
</tr>
</thead>
<tfoot>
<tr>
<th class="head1">Name</th>
<th class="head0">Description</th>
<th class="head1">Options</th>
</tr>
</tfoot>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</tbody>
</table>
#section Scripts {
#Scripts.Render("~/bundles/tables")
}
Model:
public class ApplicationRole : IdentityRole
{
[Display(Name = "Description")]
[StringLength(100, MinimumLength = 5)]
public string Description { get; set; }
}
"Error" Controller:
public class ErrorController : Controller
{
//
// GET: /Error/
public ActionResult Index(int statusCode, Exception exception)
{
Response.StatusCode = statusCode;
return View();
}
}
"Error" View:
#{
ViewBag.Title = Response.StatusCode;
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2 style="visibility:hidden">#ViewBag.Title</h2>
<div class="errorWrapper">
<h2>An internal server error #ViewBag.Title has occurred</h2>
<h1 class="pageErrorTitle" style="color:red">Error #ViewBag.Title - Page Not Found</h1>
<h3 style="color:black">You may have clicked an expired link or mistyped the address.</h3>
<br />
<a class="default" href="javascript:history.back()">Back to Previous Page</a> <a class="default" href="http://localhost:53648">Return to Dashboard</a>
</div>
Please see screenshots for more visual clarity:
Update:
According to #Munzer 's answer below, I tried to change my Index action method to take in the model route value seeing as though I am passing it in my return statement. See below:
public async Task<ActionResult> Create(ApplicationRole model)
{
if (ModelState.IsValid)
{
var role = new ApplicationRole()
{
Name = model.Name,
Description = model.Description
};
var roleManager = new RoleManager<ApplicationRole>(new RoleStore<ApplicationRole>(db));
var result = await roleManager.CreateAsync(role);
if (result.Succeeded)
{
//return RedirectToAction("Index", "Roles", model);
return RedirectToAction("SuccessfullyAddedNewRole", "Roles", model);
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
public ActionResult SuccessfullyAddedNewRole(ApplicationRole model)
{
return View(model);
}
But the error still persists. I have tried everything I can think of.
I think the error is here
return RedirectToAction("Index", "Roles", model);
you are passing route values but your index action doesn't accept any, it generate the value itself, you can simple do this instead
return RedirectToAction("Index", "Roles");,
and your index will query the new model, if you want to pass the model, you need to edit your index action accordingly, to accept role model.
Solution can be found on this SO post of mine. Fixed everything :-)
GET http://localhost/Roles/Create 500 (Internal Server Error)

using partial view in a view and getting data to partial view

I am using a partial view "_studentList" in a View "SearchStudent". In my View i have a textfield and a search button and i am showing list of students in my partial view.
My View is like as follow:
#model Practice_SQL_Validation_ALL.Models.SearchViewModel
#{
ViewBag.Title = "SearchStudent";
}
<h2>SearchStudent</h2>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand">Search</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" id="txtserch" placeholder="Enter Roll No or Name">
#*#Html.EditorFor(model => model.SEARCHCRITERA.VALUE, new { htmlAttributes = new { #class = "form-control", placeholder = "Enter Roll No or Name" } })*#
</div>
<button id="preview" type="button" class="btn btn-default">Search</button>
</form>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div id="result">
#Html.Partial("_StudentList", Model.STUDENTLIST)
</div>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
jQuery.ready(function () {
$("#result").hide();
$("#preview").click(function () {
//$("#div1").hide();
$("#result").show();
});
});
$("#preview").click(function () {
var jsonObject = {
"returnUrl": $('#txtserch').val()
};
jQuery.ajax({
type: "POST",
url: "SearchStudent",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(jsonObject),
success: function (data) { alert("Success"); },
failure: function (errMsg) {
alert("Error");
}
});
});
</script>
And my Partial View is like as follow:
#model IEnumerable<Practice_SQL_Validation_ALL.Models.Student>
#*<p>
#Html.ActionLink("Create New", "Create")
</p>*#
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.ROLLNUMBER)
</th>
<th>
#Html.DisplayNameFor(model => model.NAME)
</th>
<th>
#Html.DisplayNameFor(model => model.ADDRESS)
</th>
<th>
#Html.DisplayNameFor(model => model.PHONE)
</th>
<th>
#Html.DisplayNameFor(model => model.CLASS)
</th>
<th>
#Html.DisplayNameFor(model => model.ISNEW)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ROLLNUMBER)
</td>
<td>
#Html.DisplayFor(modelItem => item.NAME)
</td>
<td>
#Html.DisplayFor(modelItem => item.ADDRESS)
</td>
<td>
#Html.DisplayFor(modelItem => item.PHONE)
</td>
<td>
#Html.DisplayFor(modelItem => item.CLASS)
</td>
<td>
#Html.DisplayFor(modelItem => item.ISNEW)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
My ViewModel is like as follow:
namespace Practice_SQL_Validation_ALL.Models
{
public class SearchViewModel
{
private SearchCriteria searchcriteria = null;
private List<Student> studentlist = null;
public SearchCriteria SEARCHCRITERA
{
set
{
searchcriteria = value;
}
get
{
return searchcriteria;
}
}
public List<Student> STUDENTLIST
{
set
{
studentlist = value;
}
get
{
return studentlist;
}
}
public SearchViewModel()
{
searchcriteria = new SearchCriteria();
studentlist = new List<Student>();
}
}
public class SearchCriteria
{
[Display(Name = "Criteria")]
public string CRITERIA { get; set; }
[Display(Name = "Value")]
public string VALUE { get; set; }
}
public class Student
{
#region Properties
private bool m_isnew = true;
[Required]
[Display(Name = "Roll Number")]
public string ROLLNUMBER { get; set; }
[Required]
[Display(Name = "Name")]
public string NAME { get; set; }
//[Required]
[Display(Name = "Address")]
public string ADDRESS { get; set; }
//[Required]
[Display(Name = "Phone#")]
public string PHONE { get; set; }
[Display(Name = "Class")]
public string CLASS { get; set; }
[Display(Name = "Edit Mode")]
public bool ISNEW { get { return m_isnew; } set { m_isnew = value; } }
#endregion
}
}
My StudentController is as follow:
namespace Practice_SQL_Validation_ALL.Controllers
{
public class StudentController : Controller
{
public ActionResult SearchStudent()
{
SearchViewModel obj = new SearchViewModel();
ViewBag.Count = 0;
return View(obj);
}
[HttpPost]
//[AllowAnonymous]
//[ValidateAntiForgeryToken]
//[ChildActionOnly]
public ActionResult SearchStudent(string returnUrl)
{
SearchViewModel obj = new SearchViewModel();
//DAS db = new DAS();
//list = db.SearchStudentwithCriteria("RollNo", "");
//return PartialView()
obj.SEARCHCRITERA.VALUE = "Some";
obj.STUDENTLIST.Add(new Student { ADDRESS = "Address", ROLLNUMBER = "3160", NAME = "Awais", CLASS = "A", PHONE = "Phone" });
//return View(list);
ViewBag.Count = obj.STUDENTLIST.Count;
//return View(obj);
return PartialView("_StudentList", obj);
//return PartialView("_StudentList", list);
//return PartialView("_StudentList", list);
}
}
}
I want that if I click search button then ajax call SearchStudent Post function and return collection that should be displayed on partial view. Till now function is being called but response is not being returned to the view or partialview. As i am showing alertbox in both cases success and failure but system does not show alertbox in anycase. What am i doing wrong? Any help would be greatly appreciated! Please let me know if you need any more information.
Very Thanks in Advance.
Everything seems fine just the ajax succes you have to put the content like this
$.ajax({
url: "SearchStudent",
data: { "returnUrl": $('#txtserch').val()},
type: "POST",
cache: false,
success: function (data) {
$("#result").html(data); //********* This is where you have put the result into, because in success you will get the HTML
},
error: function () {
}
});
Made some changes as follow and got my issue fixed.
In Controller function "SearchStudent" returned partialview with collection.
public ActionResult SearchStudent(string returnUrl)
{
SearchViewModel obj = new SearchViewModel();
obj.SEARCHCRITERA.VALUE = "Some";
obj.STUDENTLIST.Add(new Student { ADDRESS = "Address", ROLLNUMBER = "3160", NAME = "Awais", CLASS = "A", PHONE = "Phone" });
ViewBag.Count = obj.STUDENTLIST.Count;
return PartialView("_StudentList", obj.STUDENTLIST);
}
And changed ajax call as follow:
jQuery.ajax({
type: "POST",
url: "SearchStudent",
//dataType: "json",
cache: false,
//context:
contentType: "html",
data: JSON.stringify(jsonObject),
success: function (data) { $("#result").html(data); },
failure: function (errMsg) {
$("#result").html("Error");
}
});
I think problem was majorly in ajax call. As i was returning html content from controller function but in ajax call i have mentained contentType and datatype properties as Json. That's why HTML could not been shown on success.

Refreshing a Table in a Partial View

I am trying to make some blocks of code work from a blank MVC project (no authentication) before applying its logic to my actual project but I can't seem to do it right. I'm trying to have a table in a partial view to reload/refresh/update itself every certain span of time so it'll reflect any changes that was made and that happened in another webpage/browser.
The snippet that fires a function every few second work but the rendering/refreshing is where it gets trippy. I've been following this example with no luck (Refresh Partial View Div in MVC 5).
Here are my code:
View(Index.cshtml)
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<div id="peopletablediv">
#{ Html.RenderAction("Person");}
</div>
Partial View (Person.cshtml)
#model IEnumerable
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>
Controller(PeopleController.cs)
public class PeopleController : Controller
{
private WebApplication1Context db = new WebApplication1Context();
// GET: People
public ActionResult Index()
{
return View();
}
public ActionResult Person()
{
return PartialView(db.People.ToList());
}
}
JavaScript(within the index.cshtml only since I'm just testing)
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$(document).ready(function () {
var url = '#Url.Action("Person")';
var div = $("#peopletablediv");
setInterval(function () {
div.load(url);
}, 2000);
});
</script>
I've only a few months experience in asp.net MVC and web development in general. Which part would I be getting wrong here?

MVC tab page not refreshing nested partialview after postback

I am using jquery tab ui. My second tab contains this form when posted, does not refresh a partial view I have nested. What could be the problem?
_Partial_Item_Tab.cshtml
#model Mvc5.Models.ORDER_DETAILSMetadata
#{
var ordernumber = (int)Session["Order_Number"];
}
#using (Ajax.BeginForm("Items", "Order",
new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "target"
}))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.TextBoxFor(model => model.id)
<input type="submit" value="Add" class="btn btn-default" />
}
<div id="target">
#Html.Action("Items_List", new { id = ordernumber }); <==== This does not show up after postback. Only after clicking browser refresh button does it show.
</div>
Items Controller (HttpPOST)
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Items(ORDER_DETAILSMetadata model)
{
// check to see if exists
//update order
Order order = new Order();
....
return PartialView("_Partial_Item_Tab", order);
}
Item_List Controller
public ActionResult Items_List(int id)
{
List<ORDER_DETAILS> result = db.ORDER_DETAILS.Where(p => p.Order_Number == id).ToList();
return PartialView("_Partial_Items_List", result);
}

Categories

Resources