I am submitting some info using an Ajax post which is supposed to refresh a partial view. The info gets sent to the database however on return of the partial view, the Fees.Feetype data can't be rendered as it is null.
On manual refresh, the Fees.FeeType is rendered with no problem.
How do I get the FeeType to be included in the partial view after the ajax post?
Models
public class Members
{
public virtual ICollection<Fees> Fees { get; set; }
}
public class Fees
{
public int FeeTypesId { get; set; }
public virtual FeeTypes FeeType { get; set; }
public virtual Members Members { get; set; }
}
public class FeeTypes
{
public int Id { get; set; }
public string FeeTypeName { get; set; }
}
Ajax Post
var token = $('[name=__RequestVerificationToken]').val();
var postData = {
__RequestVerificationToken: token,
FeeOccurence: feeOccField.val(),
FeeAmount: amountField.val(),
FeeStatus: statusField.val(),
FeeTypesId: typeField.val(),
FeeDate: dateField.val(),
MemberNo: memberNo
};
$.ajax({
url: '/Members/AddFees',
type: 'POST',
data: postData,
success: function (members) {
alert(result);
$("#details").html(members);
},
error: function (result) {
alert(result);
},
traditional: true
Controller
public ActionResult AddFees (Fees fees)
{
if (ModelState.IsValid)
{
db.Fees.Add(fees);
db.SaveChanges();
Members members = new Members();
members = db.Members.Find(fees.MemberNo);
return PartialView("~/Views/Members/_MemberDetails.cshtml", members);
}
}
Views
#model AccPortal.Models.Members
<div class="col-md-7 md-fees" id ="details">
#Html.Partial("_MemberDetails", Model)
</div>
//This is the partial view.
#model AccPortal.Models.Members
#foreach (var item in Model.Fees)
{
//The error happens on this line but all other Fees properties are rendered without issue.
<td class="md-fee-value"data-type="status">#item.FeeType.FeeTypeName</td>
}
These are the things you need to change in your code,
First, return a partial view with model from your Action method like this,
return PartialView("_MemberDetails", members);
Datatype should be html in your ajax method. So add this bellow line inside ajax method. You can add this line after this line data: postData,
dataType: "html",
Now in your ajax success method, change like this,
success: function (members) {
//alert(result); what is result here, that you have written
$("#details").html(''); //first make it blank then render
$("#details").html(members);
},
In your partial view, you need to check whether FeeType is there or not before render the value,
#model AccPortal.Models.Members
#foreach (var item in Model.Fees)
{
if(item.FeeType != null)
<td class="md-fee-value"data-type="status">#item.FeeType.FeeTypeName</td>
else
<td class="md-fee-value"data-type="status"></td> //You can write NA here
}
The issue with the null type was lazy loading in the end.
I had to requery the db after I had saved the changes and include Fees.FeeTypes to return the correctly populated model.
members = db.Members.Find(fees.MemberNo);
members.Fees = db.Fees.Include(x => x.FeeType).Where(x => x.Members.MemberNo.Equals(x.MemberNo)).ToList();
you need to check for null values before populating in the list to avoid null exception
#model AccPortal.Models.Members
#foreach (var item in Model.Fees)
{
if(item.FeeType != null)
<td class="md-fee-value"data-type="status">#item.FeeType.FeeTypeName</td>
}
because some data might be missing which is causing problem so with if condition it will populated only that data which is not null
Related
I've been stumped for days.
I have an index page that contains a renderpartial view. A viewmodel is passed to the index page from its controller, then passed from inside the index.cshtml to the renderpartial view as an extension. The renderpartial view is automatically updated every 10 seconds (via jquery function to the controller from the index page) to update its content, which works fine. The index page contains several checkboxfor's that filter out the contents of the renderpartial view. The problem arises when the initial renderpartial view is called when the time period has elapsed, the controller for the renderpartial view does not have the correct model data the controller for the index had prior. Boolean values in the model which were set to true while in the index controller now are false when we get to the renderpartial view. Lets begin...
My Index View:
#model SelfServe_Test2.Models.NGTransCertViewModel
...
<div class="Services_StatusTable" id="refreshme">
#{
Html.RenderPartial("_Data", Model);
}
</div>
...
#Html.CheckBoxFor(m => m.NGTransServicesModel.filter_NJDVSVR24, new { onclick = "test(id)" }) #Html.Label("NJDVSVR24", new { })
...
<script src="~/Scripts/jquery-1.12.4.js"></script>
<script type="text/javascript">
$(function () {
setInterval(function () { $('#refreshme').load('/NGTransCertServices/Data'); }, 10000); // every 10 seconds
function test(filter) {
alert(filter);
var serviceChecked = document.getElementById(filter).checked;
$.ajax({
type: "POST",
url: "/NGTransCertServices/ToggleVisibleService",
data: { 'filterOnService': filter, 'serviceChecked': serviceChecked, 'model': #Model },
//success: function (result) {
// if (result === "True")
// alert("yup");
// else
// alert("nope");
//}
});
}
</script>
The PartialView _Data.cshtml:
#model SelfServe_Test2.Models.NGTransCertViewModel
...
<table>
foreach (var item in Model.NGTransServicesList)
{
if (Model.NGTransServicesModel.filter_EBT == true)
{
if (item.Description.Contains("EBT"))
{
}
}
}
</table>
My ViewModel:
namespace SelfServe_Test2.Models
{
public class NGTransCertViewModel
{
public NGTransCertViewModel()
{
NGTransServicesModel = new NGTransCertServicesModel();
NGTransServicesList = new List<NGTransCertServicesList>();
NGTransServices = new NGTransCertServices();
}
public NGTransCertServicesModel NGTransServicesModel { get; set; }
public List<NGTransCertServicesList> NGTransServicesList { get; set; }
public NGTransCertServices NGTransServices { get; set; }
}
}
The Controller:
public class NGTransCertServicesController : Controller
{
NGTransCertViewModel NGT_VM = new NGTransCertViewModel();
NGTransCertServicesModel certServicesModel = new NGTransCertServicesModel();
public ActionResult Index()
{
NGTransCertServices certServices = new NGTransCertServices();
NGT_VM.NGTransServicesModel = certServices.InitServiceTypeCheckBoxes(certServicesModel); // sets all checkboxes to true initially.
return View(NGT_VM);
}
[OutputCache(NoStore = true, Location = System.Web.UI.OutputCacheLocation.Client, Duration = 10)] // in seconds
public ActionResult Data()
{
NGTransCertDBHandle certDBHandle = new NGTransCertDBHandle();
List<NGTransCertServicesList> List_certServices = certDBHandle.GetService();
return PartialView("_Data", NGT_VM);
}
}
Finally, the model where the values are lost:
public class NGTransCertServicesModel
{
...
public bool filter_NJDVSVR24 { get; set; }
...
}
Now then, when the Index.cshtml page is called, i run the InitServiceTypeCheckBoxes method that sets the checkbox values to true, pass the viewmodel to the index page and pass that same model to the renderpartial. All is happy until the 10s timeout is reached and _Data.cshtml is rendered. The checkbox values are now all false.
Let me add a visual element. Below is the model when returning from the controller to the index view with the Boolean set to true as desired. (stepping through)
Below is the model when the index view
Again, in the _Data.cshtml partial view
Now with a breakpoint in the Data action in the controller, that same bool value is now false
The bool does not have the true value even before the first line of code in the Data action.
NGTransCertDBHandle certDBHandle = new NGTransCertDBHandle();
I think the issue is that you're not populating your view model correctly in the Data method of your controller.
In both methods you're sending the NGT_VM property to the view, but you only populate some of the data in the Index method - this data will not be persisted or created by default when you call the Data method.
Each time a request hits a controller method, that controller is created afresh, and only the constructor and requested method are called. In the case of a request to Data the controller is created, the NGT_VM property is set back to the default NGTransCertViewModel object, with a default NGTransCertServicesModel object (the boolean property filter_NJDVSVR24 will default to false). You then create and ignore a variable List_certServices, but at no point have you updated the NGTransServicesModel property on the view model to match the values you had from the Index method.
You should probably assign the NGTransServicesList variable to the NGT_VM.NGTransServicesList after you populate it:
[OutputCache(NoStore = true,
Location = System.Web.UI.OutputCacheLocation.Client,
Duration = 10)]
public ActionResult Data()
{
NGTransCertDBHandle certDBHandle = new NGTransCertDBHandle();
List<NGTransCertServicesList> List_certServices = certDBHandle.GetService();
NGT_VM.NGTransServicesList = List_certServices;
return PartialView("_Data", NGT_VM);
}
You could either call same methods to update the NGTransServicesModel as required in the Data method, but I'm not sure that's really the behaviour you're after?
I choose from dropdown menu an item and click add => ajax call a method which return JsonResult this is all ok. Then this data should be send to another function PartialViewResult on server side: public PartialViewResult _SkupinaRow(skupinaRow skupinaRow), which generate a new tr with some textbox and labels. My problem is that no binding is made. I get Null when debuggin in _SkupinaRow(skupinaRow skupinaRow)
I have the following domain model defined:
public class skupinaRow
{
public BONUSMALUS bonusmalus { get; set; } //items
public KOLEDAR koledar { get; set; } //calendar
}
Partial View:
#model ObracunPlac.ViewModel.skupinaRow
#Html.HiddenFor(x => x.bonusmalus.bon_id)
.....
Partial view code:
public PartialViewResult _SkupinaRow(skupinaRow skupinaRow)
{
return PartialView("_SkupinaRow", skupinaRow);
}
Ajax Call:
$("#addItemPrihodki").live("click", function () {
var id = $("#prihodkidodaj option:selected").val()
var skupinaRow = {
bonusmalus:{},
koledar:{}
}
jQuery.getJSON("/Placa/getBonusMalus/?id=" + id, function (data) {
console.log("JSON Data: " + data.koledar.kol_id);
skupinaRow.koledar.kol_id = data.koledar.kol_id, //ok
skupinaRow.bonusmalus.bon_id = data.bonusmalus.bon_id, //ok
//alert(JSON.stringify(GetBonusMalusModel($("#bonusdodaj option:selected").val())));
alert(JSON.stringify(data));
// alert(skupinaRow.serialize());
$.ajax({
url: "../_skupinaRow",
cache: false,
data: JSON.stringify(skupinaRow),
//data: JSON.stringify(data),
datatype: JSON,
success: function (html) {
$("#editorRowPrihodki table tr#dodajNov").before(html);
}
,
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert('error'+"+++"+textStatus+"--- "+errorThrown);
},
});
});
return false;
});
public JsonResult getBonusMalus(int id)
{
KOLEDAR koledar = db.KOLEDAR.Single(r => r.kol_id == KoledarID);
BONUSMALUS bm = db.BONUSMALUS.Single(r => r.bon_id == id);
skupinaRow model = new skupinaRow
{
koledar =koledar,
bonusmalus = bm
};
// return Json result using LINQ to SQL
return new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = model
};
}
Debug picture: https://www.dropbox.com/s/189q080irp0ny77/1.jpg
This worked when i had one model bonusmalus but now I ned two so I created modelView.
How can I bind ViewModel-SkupinaRow to Partial View with strong type SkupinaRow ?
If you are using AJAX only to convert he value to json? then you can use this approach
Set the form with normal post back to Action in controller
use jQuery in your view and on submit of form write this.
$("form").submit(function(){
$("#DropDown_Items").val(JSON.stringify(data));
});
Now you can use this in your Action Method.
I like to do one simple control for day transactions.
That need to show me how much transaction we have this day (close or open trans) and when the manager click the number of transaction I would like to send all this list of transactions into a nice table.
But I can't find the way to do it. Not even across the web.
here is my try but nothing.
I am open for suggestion =)
Here is my ViewModel
public class SIMcontrolsViewModel
{
public DTControls DTransactionControl { get; set; }
}
public class DTControls
{
public DateTime TDate { get; set; }
public int NumOfTransaction { get; set; }
public List<SIMsale> SIMsaleList { get; set; }
public DTControls()
{
SIMsaleList = new List<SIMsale>();
}
}
the Controller look like I fill all the data and I sent it to view
[AdminAuthorization]
public ActionResult DateTransactionsControl(DateTime? date)
{
SIMcontrolsViewModel vm = new SIMcontrolsViewModel();
vm.DTransactionControl = new DTControls();
if (!date.HasValue)
date = DateTime.Now;//.Today;
vm.DTransactionControl.TDate = date.Value;
try
{
using (CompanyContext db = new CompanyContext())
{
var saleLst = db.SIMsales.ToList();
foreach (var sale in saleLst)
{
if (..)
vm.DTransactionControl.SIMsaleList.Add(sale);
}
var tCount = vm.DTransactionControl.SIMsaleList.Count;
vm.DTransactionControl.NumOfTransaction = tCount;
}
}
catch (Exception ex)
{..}
return View(vm);
}
Now on my View I try to send this list from this #Html.ActionLink like we can see here.
#model oCc.IPToGo.ViewModel.SIMcontrolsViewModel
<fieldset>
<table border="0" class="display">
<thead>
<tr>
<th style="width:100px">Date</th>
<th style="width:100px">#Html.DisplayNameFor(model => model.DTransactionControl.NumOfTransaction)</th>
</tr>
</thead>
<tbody>
<tr style="text-align: center">
<td>#Model.DTransactionControl.TDate.ToShortDateString()</td>
#if (Model.DTransactionControl.NumOfTransaction != 0)
{
<td>
#Html.ActionLink(Model.DTransactionControl.NumOfTransaction.ToString(), "../SIMsale/",
new { sell = Model.DTransactionControl.SIMsaleList },
new { style = "font-weight: bold; color: Highlight" })
</td>
}
else
{
<td style="color:red">0</td>
}
</tr>
</tbody>
</table>
</fieldset>
The problem is that the view/controller who supposed to get this list is getting an empty list.
10Q =)
You can simply sent the SIMsales condition like sellerId on your ViewModel and a Hidden field on Razor to keep the data and on pthe post function (on your controller) just retrive all of those SIMsales that you count on the Get func.
(I know that was two year before but maybee that can help)
I would associate an id with the transaction count and pass that back to the controller through an ajax call
$.ajax({
url: "#(Url.Action("Action", "Controller"))",
type: "POST",
cache: false,
async: true,
data: { id: 'associatedID' },
success: function (result) {
$(".Content").html(result);
}
});
create a partial view for displaying the table and on your controller populate and return the partial view using the passed id
public PartialViewResult BuildTable(int id){
Model model = (get results from database for id)
return PartialView("_Partial", model);
}
then put a div on your view with a class of Content (or whatever you want to call it). Hopefully this helps.
I am having trouble building this code - I have an api controller which gets its data from the service layer via the models and this is what i have:
api controller
public class RoleApiController : ApiController
{
private RoleService _roleService = new RoleService();
public RoleUser GetRoleUser(int sectionID)
{
if (sectionID != null)
{
return _roleService.GetUsers(sectionID);
}
throw new HttpResponseException(HttpStatusCode.NotFound);
}
}
Model
public partial class RoleView
{
public RoleView()
{
this.Users = new HashSet<RoleUser>();
}
public ICollection<RoleUser> Users { get; set; }
}
public class RoleUser
{
public string Name { get; set; }
public string Email { get; set; }
}
ERROR MESSAGE:
Cannot implicitly convert type System.Collections.Generic.IEnumberable<...RoleUser> to RoleUser. An explicit conversion exists(missing a cast?)
for this line: return _roleService.GetUsers(sectionID);
JavaScript
<div>
Name: <span id="name"></span>
</div>
<div>
Email: <span id="email"></span>
</div>
<script type ="text/javascript" src="~/Scripts/jquery-1.9.1.min.js"></script>
<script type ="text/javascript">
getRoleUser(9, function (roleUser) {
$("#name").html(roleUser.Name);
$("#email").html(roleUser.Email);
});
function getRoleUser(id, callback) {
$.ajax({
url: "/api/RoleUser",
data: { id: id },
type: "GET",
contentType: "application/json;charset=utf-8",
statusCod: {
200: function (roleUser) { callback(roleUser); },
404: function () { alter("Not Found!"); }
}
success: function(result){
result.each(function())
}
});
}
</script>
Umm your returning a collection of users when you should be returning just one? I can't really tell whether you actually want a collection or not from the code you've shown, but that is your issue.
This will let your code compile, but may not be the solution you want:
return _roleService.GetUsers(sectionID).FirstOrDefault();
Your method declaration says it returns RoleUser (singular) while your method would hint it returns a collection. So either you need to fix the method to return a list or return only a single result from your GetUsers method.
When is it typical to use the JsonResult action in an ASP.NET MVC 3 application?
From where is the JsonResult usually called; from another action or an actionlink rendered in the html?
Can you give me some examples where you want json instead of a typical view?
Say, for example you wanted to populate a jQuery autocomplete with a list of values based on a selection of another field, so you can't determine the data on page load. I would typically call an action method in a $.ajax call, then return an array of items to populate the autocomplete with.
Example, here's my jQuery, one function for the call and another that gets called to populate the automcomplete with received data:
$(function() {
$.ajax({
url: '#Url.Action("GetHomes", "Account")',
type: "POST",
datatype: "json",
success: function (data) {
if (data.Success || data.Success == null) {
WireUpHomesData(data);
} else {
ShowErrorDialog();
}
}
});
ShowDialog();
});
function WireUpHomesData(data) {
var homes = new Array();
for (var i = 0; i < data.length; i++) {
homes[i] = { label: data[i].HomeName, text: data[i].HomeId, icon: data[i].HomeIcon, desc:data[i].HomeAddress };
}
$("#home").autocomplete({
source: homes,
select: function (event, item) {
homeUrl = '#Url.Action("Site", "Sites")/' + item.item.text;
}
}).data("autocomplete")._renderItem = function (ul, item) {
return $("<li></li>")
.data("item.autocomplete", item)
.append("<a><span class='" + item.icon + "'/><span class='fs-ui-autocomplete-home'>" + item.value + "</span><br>" + item.desc+ "</a>")
.appendTo(ul);
};
$(".ui-autocomplete").addClass("fs-ui-autocomplete");
}
And here is my controller:
public JsonResult GetHomes()
{
return Json(RequiresAclAttribute.HomesForUser());
}
And here's the method signature for the method that's called:
public IEnumerable<HomeInfo> HomesForUser()
And for clarity, here's the HomeInfo class:
public class HomeInfo
{
public string HomeId { get; set; }
public string HomeName { get; set; }
public string DisplayName { get; set; }
public string HomeAddress { get; set; }
public string HomeIcon { get; set; }
}
JsonResult is a subclass derived from ActionResult class. You can use this when you want to return a Json object.
public JsonResult GetItems()
{
var jsonResult=new { Id = "23", Name = "Scott"};
return Json(jsonResult,JsonBehaviour.AllowGet);
}
This will return the same result as
public ActionResult GetItems()
{
var jsonResult=new { Id = "23", Name = "Scott"};
return Json(jsonResult,JsonBehaviour.AllowGet);
}
Possible use of this is to get some chunk of data in asynchronous way. Ex : Imagine you have a drop down where you are showing the states and when user selects a state, you want to to bring the list of cities belongs to the state and show it in the page without a page refrest. you can call use jQuery ajax /getJson method (short hand of jQuery get with json as datatype) method to get this data from an ActionMethod which returns Json data.
A small example to call an Action method which returns the Json data
$(function(){
$.getJSON('YourController/GetItems', function(data) {
alert(data.Id);
alert(data.Name );
});
});
With JsonResult class the response content type will be "application/json" if nothing is specified explicitly. Internally The ExecuteResult method uses JavaScriptSerializer to Serialize the content when returning data.
The JsonResult is very usefull wehn making ajax calls from javascript, e.g. using getJSON from jQuery: http://api.jquery.com/jQuery.getJSON/
The benefit of JsonResult is it returns a JSON formatted result without effort.
An Ajax request from a client script that does not involve a full page load. Basically.
Whenever there is client side processing and client need that data use jsonresult like in autofill or remote validation