Partial view won't render after ajax call - asp.net-mvc

I need to pass list of Objects. I am passing the data threw ajax call, ajax returns the results as expected, so the ajax call gets the correct results but partial view won't render.
Controller
[HttpPost]
public ActionResult GetXlFile()
{
List<ListMatchDetails> lstPreview = new List<ListMatchDetails>();
if (System.Web.HttpContext.Current.Request.Files.AllKeys.Any())
{
var xlFile = System.Web.HttpContext.Current.Request.Files["FileToPreview"];
HttpPostedFileBase filebase = new HttpPostedFileWrapper(xlFile);
if (null != filebase && filebase.ContentLength > 0)
{
if (String.Compare(filebase.ContentType, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", true, System.Globalization.CultureInfo.InvariantCulture) == 0)
{
using (Stream stream = filebase.InputStream)
{
IExcelDataReader reader = null;
if (filebase.FileName.EndsWith(".xls"))
{
reader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (filebase.FileName.EndsWith(".xlsx"))
{
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
reader.IsFirstRowAsColumnNames = true;
DataSet dsResult = reader.AsDataSet();
DataTable dtResult = dsResult.Tables[0];
if (dtResult.Rows.Count > 0)
{
foreach (DataRow dr in dtResult.Rows)
{
ListMatchDetails lmd = new ListMatchDetails();
lmd.FirstName = (dr[0] != DBNull.Value) ? dr[0].ToString() : string.Empty;
lmd.LastName = (dr[1] != DBNull.Value) ? dr[0].ToString() : string.Empty;
lstPreview.Add(lmd);
}
}
reader.Close();
}
}
}
}
return PartialView("_ExcelGrid", lstPreview);
}
view
#using app.Models;
#model IEnumerable<ListMatchDetails>
#{
if (Model.Count() > 0)
{
ListMatchDetails row = Model.FirstOrDefault();
<table class="table table-hover table-responsive scrollable table-striped ">
<thead id="tableHeader">
<tr>
<td>
#Html.LabelFor(x => row.FirstName)
</td>
<td>
#Html.LabelFor(x => row.LastName)
</td>
</tr>
</thead>
<tbody class="pre-scrollable">
#foreach (var record in Model)
{
<tr>
<td>
#Html.ValueForModel(record.FirstName)
</td>
<td>
#Html.ValueForModel(record.LastName)
</td>
</tr>
}
</tbody>
</table>
}
}
jquery:
$('#btnPreview').click(function () {
var formData = new FormData();
var files = $("#btnbrowse").get(0).files;
if (files.length > 0) { formData.append("FileToPreview", files[0]); }
$.ajax({
url: '/ListMatch/GetXlFile',
type: 'POST',
dataType: 'json',
data: formData,
processData: false,
contentType: false,
success: function (result) {
//$('#record').html(result)
$('._ExcelGrid').json(result);
},
error: function () {
//alert('Click Called');
}
});
});

Right off the bat comparing your action method to your jQuery ajax call, it looks like you're trying to parse the result of the ajax call as a JSON string but you're returning the _ExcelGrid partial view. Unless the _ExcelGrid partial view is returning valid JSON, that's going to break when it attempts to parse it as JSON.
I can't tell how it's supposed to be because I'm not sure what ._ExcelGrid is in your view, but generally speaking you can either change the action method to return JSON instead of a partial view and then parse/handle the JSON on the client side or assign the returned partial view to the element with $("._ExcelGrid").html(result). Which way you handle it is up to you.
If you opt to return the partial view, for completionist sake I'd change the dataType in your ajax call to html, because you're not expecting JSON anymore. You probably also want to set the contentType to the type of content that you're sending to the server, you can occasionally run into funny errors if you're not explict.

it looks like you need to use $('#record').html(result). Make sure you have something like
<div id="record">
</div>

This will get you past your roadblock. Please let me know if you want me to add more code pertaining to your question.
_ExcelGrid.cshtml
A Partial View
Controller:
public class HomeController : Controller
{
[HttpPost]
public PartialViewResult GetXlFile()
{
return PartialView("_ExcelGrid");
}
public ActionResult GetXlFile(int? id)
{
return View();
}
View:
#{
Layout = null;
}
<!DOCTYPE html>
#*credit to
https://stackoverflow.com/questions/5410055/using-ajax-beginform-with-asp-net-mvc-3-razor*#
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index800</title>
<script src="~/Scripts/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(function () {
$('form').submit(function (event) {
$.ajax({
url: this.action,
type: "POST",
data: $(this).serialize(),
success: function (result) {
$('#result').html(result);
}
});
return false;
});
});
</script>
</head>
<body>
<form>
<div>
#using (Html.BeginForm())
{
<input type="submit" value="OK" />
}
<div id="result"></div>
</div>
</form>
</body>
</html>

Greet for the day !!
Have you defined the partial view on your main page? if not you need to define partial view on your main page just like
<div id="dvExcelGrid">
#Html.Partial("_ExcelGrid", "your model")
</div>

Related

C# Core MVC - <script> populate a textarea after dropdown list onchange event

I'm trying to fill a text area on my MVC view after retrieving a subset of data. I can get the data, but need to update the view with the returned data
Here is the code I have tried:
<div class="box-shadow">
<p>Please select an Area Path and Iteration Path below:</p>
<table>
<tr>
<th>Area Path</th>
<th>Iteration Path</th>
</tr>
<tr>
<td>
#Html.DropDownList("MySpecialAreaPathsList",((List<string>)ViewBag.myAreaPathsList).Select(m => new SelectListItem { Text = m, Value = m }),
null, new { #onchange = "GetAreaPathValue()" })
</td>
<tr>
<td>
<textarea class="text-info" id="txtLog" style="width:1080px;height:200px"></textarea>
</td>
function GetAreaPathValue() {
var selectedElement = document.querySelector('#MySpecialAreaPathsList');
var option = selectedElement.value;
$.ajax({
url: '#Url.Action("GetAreaPathChildren", "MyController")',
type: "GET",
data: { 'areapathText': option },
success: function (data) { $('#txtLog').value(data) }
})
}
Can someone help me with getting the return data from GetAreaPathChildren (the return value is a List but I'd be happy just getting a string (or any value actually)
I'm trying to fill a text area on my MVC view after retrieving a
subset of data. I can get the data, but need to update the view with
the returned data
Well, based on your shared code snippet, I have successfully reproduced your scenario. The reason why your data is not appending to your textarea as expected has pretty obvious reason. If you check your browser console.log you would get below error:
Reason Of Error:
You are using wrong javascript attribute value. Its incorrect. It should be val insteaed of value. Therefore, your code snippet would be
$('#txtLog').val(data.message) instead of
$('#txtLog').value(data)
Complete Solution
Controller:
public class AppendTextAreaController : Controller
{
public IActionResult Index()
{
List<string> MySpecialAreaPathsList = new List<string>();
MySpecialAreaPathsList.Add("C#");
MySpecialAreaPathsList.Add("SQL");
MySpecialAreaPathsList.Add("Asp.net core");
ViewBag.myAreaPathsList = MySpecialAreaPathsList;
return View();
}
[HttpGet]
public JsonResult GetAreaPathChildren(string areapathText)
{
return new JsonResult(new { message = string.Format("Data From Controller and parameter passed: {0}",areapathText) });
}
}
View:
<div class="box-shadow">
<p>Please select an Area Path and Iteration Path below:</p>
<table>
<tr>
<th>Area Path</th>
<th>Iteration Path</th>
</tr>
<tr>
<td>
#Html.DropDownList("MySpecialAreaPathsList",((List<string>)ViewBag.myAreaPathsList).Select(m => new SelectListItem { Text = m, Value = m }),
null, new { #onchange = "GetAreaPathValue()" })
</td>
<tr>
<td>
<textarea class="text-info" id="txtLog" style="width:1080px;height:200px"></textarea>
</td>
</table>
</div>
#section Scripts {
<script>
function GetAreaPathValue() {
alert("Inside Func");
var selectedElement = document.querySelector('#MySpecialAreaPathsList');
var option = selectedElement.value;
$.ajax({
url: '#Url.Action("GetAreaPathChildren", "AppendTextArea")',
type: "GET",
data: { 'areapathText': option },
success: function (data) {
console.log(data);
$('#txtLog').val(data.message)
}
})
}
</script>
}
Output:
Note:
Remember that, if you return your data from controller like this
var message = string.Format("Data From Controller and parameter passed: {0}", areapathText);
return new JsonResult(message);
In that scenario, you should get this data in your view as below:
$('#txtLog').val(data)
You could refer below code snippet as well.
[HttpGet]
public JsonResult GetAreaPathChildren(string areapathText)
{
var message = string.Format("Data From Controller and parameter passed: {0}", areapathText);
return new JsonResult(message);
}

ASP.NET MVC 5: How do you render a partial view in a div from an action link?

I am new to ASP.NET and web development of any kind. I have searched for many hours for a solution to my problem, but I can't seem to get my partial view to show up in the div.
What is happening is the view is showing up, but it's replacing the entire page instead of showing up in the div within the main page.
My controller looks something like this:
public class MyController
{
public ActionResult ShowView(int id)
{
// get view model from id
return PartialView(viewModel);
}
}
My Main View looks something like this
#model List<viewModelType>
<div>
#foreach (var item in Model)
{
<div>
#Html.ActionLink(item.Name, "ShowView", new { id = item.ID }, new { #class = "btn-sm" })
</div>
}
</div>
<div>
// here is where I want to partial view to go!
</div>
This is what the partial view looks like:
#model viewModelType
<div>Model.DataToDisplay</div>
Would this work for you?
[ChildActionOnly]
public class MyController
{
public ActionResult ShowView(int id)
{
// get view model from id
return PartialView(viewModel);
}
}
And in your view:
<div>
// here is where I want to partial view to go!
#Html.Action("ShowView")
</div>
Okay I figured it out with Christos' help.
The main view should look like this:
#model List<viewModelType>
<div>
#foreach (var item in Model)
{
<div>
<button class="js-showViewBtn" data-itemId=#item.ID>item.Name</button>
</div>
}
</div>
<div class="js-show-view">
// here is where I want to partial view to go!
</div>
<script type="text/javascript">
$(function () {
$('.js-showViewBtn').click(function (e) {
e.preventDefault();
var itemId = $(this).data("itemId");
$.ajax({
method: "GET",
url: "/MyController/ShowView",
data: { id: itemId },
cache: false
}).success(function(data){
$('.js-show-view').html(data);
});
})
});
</script>
For some reason the id of the item was not being returned, so I tried it like this and it worked. Hope this helps others too.
Thanks for your help Christos.
You need a bit of JavaScript to do that you want. Basically, you have to wire up a click event handler for your links and when the user click on one of them an ajax request would be triggered.
#model List<viewModelType>
<div>
#foreach (var item in Model)
{
<div>
#Html.ActionLink(item.Name, "ShowView", new { id = item.ID }, new { #class = "btn-sm js-show-view-btn" })
</div>
}
</div>
<div class="js-show-view">
// here is where I want to partial view to go!
</div>
<!-- Before the following script been loaded, he jQuery should have been loaded -->
<script>
$(function(){
$(".js-show-view-btn").click(function(e){
e.preventDefault();
$.ajax({
method: "GET",
url: "/MyController/ShowView",
data: { id = $(e).id },
cache: false
}).success(function(data)
{
$(".js-show-view").html(data);
});
})
});
</script>

ASP.NET MVC5 EF6 PagedList as Partial is returning whole page BUT only sometimes

What can be causing the following script to only fire randomly when it feels like it? i.e. if I comment in the alert(44); it pops up sometimes once at the start when I click on page 2. Then I click other pages in the pager and no alert(44) but I get the WHOLE page reloading and not just the partial
So in effect its like I have no problem but only if I can force the Javascript Click below to run all the time when the Pager bar is clicked
$(function () {
$('#myPager').on('click', 'a', function () {
//alert(44);
$.ajax({
url: this.href,
type: 'GET',
cache: false,
success: function (result) {
$('#ResultsList').html(result);
}
});
return false;
});
});
The Javascript above is inside "$(document).ready(function () {" and part of my main file called index.cshtml
Also in index.cshtml I have
<div id="ResultsList" style="clear:both;">
#Html.Partial("IndexSearchResults")
</div>
In IndexSearchResults I have :
#model PagedList.IPagedList<AscendancyCF.Domain.Premise>
<p>
Results <span class="badge">#string.Format("{0:n0}", ViewBag.ResultCount)</span> of <span class="badge">#string.Format("{0:n0}", ViewData["TotalRecords"])</span> Premises <div id="LoadingGif"></div>
</p>
<table class="table" id="myTable" data-link="row">
<thead>
<tr>
<th>
Core Spid
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.CoreSPID)
</td>
</tr>
}
</tbody>
</table>
<div id="myPager">
#Html.Partial("Pager")
</div>
Finally Controller Code is :
public ActionResult Index()
{
if (!Request.IsAuthenticated)
return View("~/Views/Shared/NotAuthorised.cshtml");
ViewData["TotalRecords"] = _db.FindAllPremises().Count();
ViewData["ResultCount"] = 0;
ViewBag.InitialPageCount = 10;
var obj = _db.FindAllPremiseEmpty();
return View("Index", obj.ToPagedList(1, 10));
}
public ActionResult IndexSearch(int? page, string searchSPID, string searchPremise, string searchPostcode, int optVacant, int OptOurSpids, string searchCompany, string searchLP)
{
var searchResults = getSearchResults(searchSPID, searchPremise, searchPostcode, optVacant, OptOurSpids, searchCompany, searchLP);
ViewData["TotalRecords"] = _db.FindAllPremises().Count();
ViewBag.ResultCount = searchResults.Count();
ViewBag.searchSPID = searchSPID;
ViewBag.searchPremise = searchPremise;
ViewBag.searchPostcode = searchPostcode;
ViewBag.optVacant = optVacant;
ViewBag.OptOurSpids = OptOurSpids;
ViewBag.searchCompany = searchCompany;
ViewBag.searchLP = searchLP;
int pageSize = 5;
int pageNumber = (page ?? 1);
if (searchResults == null)
return View("NotFound");
if (Request.IsAjaxRequest())
{
return PartialView("IndexSearchResults", searchResults.ToPagedList(pageNumber, pageSize));
}
return View("Index", searchResults.ToPagedList(pageNumber, pageSize));
}
I have code that gets fired from SEARCH button in index.aspx. This now only runs once and fails after I have clicked on the pager, here it is:
function performSearch() {
var url = '/Premise/IndexSearch';
var data = {
searchSPID: $('#SearchSPID').val().toString(),
searchPremise: $('#SearchPremise').val().toString(),
searchPostcode: $('#SearchPostcode').val().toString(),
optVacant: $("input[name='OptVacantOrOccupied']:checked").attr("id"),
OptOurSpids: $("input[name='OptOurSpids']:checked").attr("id"),
SearchCompany: $('#SearchCompany').val().toString(),
SearchLP: $('#SearchLP').val().toString()
};
$("#ResultsList").load(url, data, function () {
$('#LoadingGif').empty();
});
$('#LoadingGif').empty().html('<img src="/Content/images/ajax-loader.gif" width=31 height=31 alt="Loading image" />');
}
Your #myPager event handler is lost when the page is updated due to the element being removed from the dom. If you want to do this kind of thing, always attach your dom event to a part of the page that doesn't get removed, your handlers won't get destroyed then.
Try and keep to as close to your original element as possible to stop a mass of handlers slowing down your page.
Here is an updated script:
$(function () {
$('#ResultsList').on('click', '#myPager a', function (evt) {
var target = $(evt.currentTarget);
$.ajax({
url: target.attr("href"),
type: 'GET',
cache: false,
success: function (result) {
$('#ResultsList').html(result);
}
});
return false;
});
});
I haven't tested this, but it looks right.

How to use jquery or ajax to update razor partial view in c#/asp.net for a MVC project

In a MVC partial view file, I build one Html.TextBox and two submit buttons. These two buttons will increase/decrease the Html.TextBox value once clicked. The Html.TextBox displayed value will change accordingly.However, once I need to update the #refTable div based on the new value after click. The page or section never updated. Codes are below, where some comments are added for explanation purpose. Thanks for your help.
//******* cshtml file **********//
<body>
</body>
<input type="submit" value="PrevY" name="chgYr2" id="pY" />
#{
var tempItem3 = Model.First(); // just give the first entry from a database, works.
if (ViewData["curSel"] == null)
{
#Html.TextBox("yearSelect3", Convert.ToDateTime(tempItem3.Holiday_date).Year.ToString());
ViewBag.selYear = Convert.ToDateTime(tempItem3.Holiday_date).Year; // just initial value, works
ViewData["curSel"] = Convert.ToDateTime(tempItem3.Holiday_date).Year;
}
else
{
#Html.TextBox("yearSelect3", ViewData["curSel"].ToString());
}
}
<input type="submit" value="NextY" name="chgYr2" id="nY" />
<script type="text/javascript">
$(document).ready(function () {
$(document).on("click", "#nY", function () {
var val = $('#yearSelect3').val();
$('#yearSelect3').val((val * 1) + 1);
var dataToSend = {
id: ((val * 1) + 1)
}
// add some jquery or ajax codes to update the #refTable div
// also ViewBag.selYear need to be updated as ((val * 1) + 1)
// like: ViewBag.selYear = ((val * 1) + 1);
// any similar temp variable is fine
});
});
$(document).on("click", "#pY", function () {
var val = $('#yearSelect3').val();
$('#yearSelect3').val((val * 1) - 1);
var dataToSend = {
id: ((val * 1) - 1)
}
});
});
</script>
<span style="float: right">Set Holiday Calender for 2013</span>
<span id="btnAddHoliday">#Html.ActionLink("Add Holiday", "Create", null, new { id = "addHilBtn" })</span>
<div id="refTable">
<table class="tblHoliday" style="width: 100%;">
<th>
Holiday
</th>
<th>
Dates
</th>
<th>Modify</th>
<th>Delete</th>
</tr>
#foreach (var item in Model)
{
if ( Convert.ToDateTime(item.Holiday_date).Year == ViewBag.selYear)
// if the ViewBag.selYear is hard code, this selection "works"
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Holiday_Name)
</td>
<td>
#item.Holiday_date.Value.ToString("MM/dd/yyyy")
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { })
</td>
<td>
#Html.ActionLink("Delete", "Delete", new { })
</td>
</tr>
}
}
</table>
</div>
You'll need AJAX if you want to update a part of your page without reloading the entire page.
main cshtml view
<div id="refTable">
<!-- partial view content will be inserted here -->
</div>
#Html.TextBox("yearSelect3", Convert.ToDateTime(tempItem3.Holiday_date).Year.ToString());
<button id="pY">PrevY</button>
<script>
$(document).ready(function() {
$("#pY").on("click", function() {
var val = $('#yearSelect3').val();
$.ajax({
url: "/Holiday/Calendar",
type: "GET",
data: { year: ((val * 1) + 1) }
})
.done(function(partialViewResult) {
$("#refTable").html(partialViewResult);
});
});
});
</script>
You'll need to add the fields I have omitted. I've used a <button> instead of submit buttons because you don't have a form (I don't see one in your markup) and you just need them to trigger javascript on the client side.
The HolidayPartialView gets rendered into html and the jquery done callback inserts that html fragment into the refTable div.
HolidayController Update action
[HttpGet]
public ActionResult Calendar(int year)
{
var dates = new List<DateTime>() { /* values based on year */ };
HolidayViewModel model = new HolidayViewModel {
Dates = dates
};
return PartialView("HolidayPartialView", model);
}
This controller action takes the year parameter and returns a list of dates using a strongly-typed view model instead of the ViewBag.
view model
public class HolidayViewModel
{
IEnumerable<DateTime> Dates { get; set; }
}
HolidayPartialView.csthml
#model Your.Namespace.HolidayViewModel;
<table class="tblHoliday">
#foreach(var date in Model.Dates)
{
<tr><td>#date.ToString("MM/dd/yyyy")</td></tr>
}
</table>
This is the stuff that gets inserted into your div.
The main concept of partial view is returning the HTML code rather than going to the partial view it self.
[HttpGet]
public ActionResult Calendar(int year)
{
var dates = new List<DateTime>() { /* values based on year */ };
HolidayViewModel model = new HolidayViewModel {
Dates = dates
};
return PartialView("HolidayPartialView", model);
}
this action return the HTML code of the partial view ("HolidayPartialView").
To refresh partial view replace the existing item with the new filtered item using the jQuery below.
$.ajax({
url: "/Holiday/Calendar",
type: "GET",
data: { year: ((val * 1) + 1) }
})
.done(function(partialViewResult) {
$("#refTable").html(partialViewResult);
});
You can also use Url.Action for the path instead like so:
$.ajax({
url: "#Url.Action("Holiday", "Calendar", new { area = "", year= (val * 1) + 1 })",
type: "GET",
success: function (partialViewResult) {
$("#refTable").html(partialViewResult);
}
});

How do I Show/Hide partial view based on result I get from service call using jQuery AJAX in MVC4?

I want to have a page where I can enter loan number then I will call a WCF get service to see if a loan number is valid. If loan# is valid, I want to show loan related data (partial view) on the same page.
Here is my main View:
#model LoanStatus.Web.Models.Validate
#{
ViewBag.Title = "Validate";
}
#section Scripts {
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/jqueryui")
}
<script type="text/javascript">
jQuery(function ($) {
$("#txtssn").mask("9999");
});
function validateRequest() {
var $form = $('form');
if ($form.valid()) {
$.support.cors = true;
var lnkey = $('#txtlnkey').val();
$.ajax({
type: "GET",
url: "http://localhost:54662/Service1/ValidateRequest/" + encodeURIComponent(lnkey),
contentType: "application/json; charset=utf-8",
dataType: "json", //jsonp?
success: function (response) {
$('#Result').html('Loading....');
if (response.ValidateRequestResult.toString().toUpperCase() == 'TRUE') {
alert('validated');
} else {
alert('cannot validated' + response.ValidateRequestResult.toString().toUpperCase());
//$("#Result").hide();
}
$('#Result').html(response.ValidateRequestResult);
//alert(response.ValidateRequestResult.toString());
},
error: function (errormsg) {
alert("ERROR! \n" + JSON.stringify(errormsg));
}
});
//
} else {
$('#Result').html('Input Validation failed');
}
}
</script>
#using (Html.BeginForm()) {
<fieldset>
<legend>Log in Form</legend>
<ol>
<li>
#Html.LabelFor(m => m.LoanKey, new{})
#Html.TextBoxFor(m => m.LoanKey, new { #id = "txtlnkey" })
#Html.ValidationMessageFor(m => m.LoanKey)
</li>
</ol>
<input type="button" value="Get Status" onclick="javascript:validateRequest();" />
</fieldset>
}
<div id="Result">
#if (ViewBag.Validated)
{
#Html.Action("GetLoanInfo");
}
</div>
Below is my controller:
namespace LoanStatus.Web.Controllers
{
public class ValidateController : Controller
{
//
// GET: /Validate/
[HttpGet]
public ActionResult Index()
{
var model = new Validate() {LoanKey = "", Last4Ssn = ""};
ViewBag.Validated = false;
return View(model);
}
[HttpPost]
public ActionResult Index(Validate model, bool validated)
{
// do login stuff
ViewBag.Loankey = model.LoanKey;
ViewBag.Validated = true;
return View(model);
}
public ActionResult GetLoanInfo() // SHOWs Search REsult
{
return PartialView("_LoanInfoPartial", ViewBag.Loankey);
}
}
}
I want to have '#Html.Action("GetLoanInfo");' rendered only if jQuery AJAX service call returns TRUE (Where I have alert('validated'). I am not sure how to do that. My issue can be resolved if I can set value to ViewBag.Validated in success:function(). But based on what I read, it cannot be set in jQuery.
I tried $("#Result").hide(); and $("#Result").show(); but it did not work. Please help.
Can you try with this:
In your function validateRequest() ajax success, at the place where you are showing alert('validated'); use this and try:
$('#Result').load('#Url.Action("GetLoanInfo", "Validate")');
In your view make Result div empty
<div id="Result"> </div>
Tell me if it helps.

Resources