How can i pass the timestamp with my Ajax.actionlink - entity-framework-4.1

i have the folloiwng Index view that show a list of objects and a Delete Ajax.actionlink beside each object:-
<legend>#Model.Where(d => d.VisitStatu.Description.ToUpper().Equals("ASSINGED")).Count() #ViewBag.subtitle</legend>
<table>
<tr>
<th>Patient Full Name </th>
<th>Created BY</th>
<th></th>
</tr>
#foreach (var item in Model.Where(d => d.VisitStatu.Description.ToUpper().Equals("ASSINGED")))
{
<tr id = #item.VisitID>
<td>#Html.DisplayFor(modelItem => item.Patient.FullName)</td>
<td>#Html.DisplayFor(modelItem => item.CreatedBy)</td>
<td>#Ajax.ActionLink("Delete",
"Delete", "Visit",
new { id = item.VisitID },
new AjaxOptions
{
HttpMethod = "Post",
OnSuccess = "deletionconfirmation",
OnFailure = "deletionerror"
}
</td> </tr>
where the Ajax.actionlink will call the following Post Action Method:-
[HttpPost]
public ActionResult Delete(int id)
{ try
{ var v = repository.GetVisit(id);
if (!(v.Editable(User.Identity.Name)))
{return View("NotFound"); }
repository.DeleteVisit(v);
repository.Save();
return Json(new { IsSuccess = "True", id = id, description = v.Date.ToString() }, JsonRequestBehavior.AllowGet);
}
catch (DbUpdateConcurrencyException)
{
return Json(new { IsSuccess = "False" }, JsonRequestBehavior.AllowGet);
}
catch (OptimisticConcurrencyException)
{
return Json(new { IsSuccess = "False" }, JsonRequestBehavior.AllowGet);
}}
But currently if the user clicks on the Delete link and the record was modified by another user then no DbUpdateConcurrencyException will be raised ,, as i am not passing the timestamp to the delete action method... so how i can include the timestamp values with the Delete ajax.actionlink?
//Hint the object already include a timestamp propert.
BR

You could pass it as query string parameter, the same way you are passing the id:
#Ajax.ActionLink(
"Delete",
"Delete",
"Visit",
new {
id = item.VisitID,
timestamp = item.Timestamp
},
new AjaxOptions
{
HttpMethod = "Post",
OnSuccess = "deletionconfirmation",
OnFailure = "deletionerror"
}
)
and then have the Delete controller action take a timestamp parameter.

Related

Pass JsonData from view and receive JSON return value in view

I'm trying to send data by user input to controller using ajax and want to execute query by user input. Later I want to return the query result to same view by a JsonResult. I have successfully sent data to controller but can't find the way to return the query and shows it in same view.
View:
#{
ViewBag.Title = "Deposit";
}
<table class="table table-bordered table-striped">
<tr>
<th>Sr No</th>
<th>Party Name </th>
<th>Phone Number</th>
<th>Deposit</th>
<th>Action</th>
</tr>
#{
int count = 1;
}
#for (int i = 0; i < Model.Rows.Count; i++)
{
<tr>
<td>#count</td>
<td>#Model.Rows[i][1]</td>
<td>#Model.Rows[i][2]</td>
<td>#Html.TextBox("Deposit", null, new { placeholder = "Input" })</td>
<td> <input type="submit" value="Deposit" id="btnClick" /></td>
</tr>
count++;
}
</table>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
#section scripts{
<script type="text/javascript">
$(document).ready(function () {
var ProductPack = JSON.stringify({
'Deposit': $("#Deposit").val(),
});
$("#btnClick").click(function () {
var f = {};
f.url = '#Url.Action("InsertDeposit", "Admin")';
f.type = "POST";
f.dataType = "json";
f.data = JSON.stringify({
'Deposit': $("#txtValue").val()
});
f.contentType = "application/json";
f.success = function (response) {
location.reload();
if (response == true) {
window.location.href='Negative';
}
alert("success");
};
f.error = function (response) {
alert("failed");
};
$.ajax(f);
});
});
</script>
}
#{
ViewBag.Title = "Deposit";
}
<table class="table table-bordered table-striped">
<tr>
<th>Sr No</th>
<th>Party Name </th>
<th>Phone Number</th>
<th>Deposit</th>
<th>Action</th>
</tr>
#{
int count = 1;
}
#for (int i = 0; i < Model.Rows.Count; i++)
{
<tr>
<td>#count</td>
<td>#Model.Rows[i][1]</td>
<td>#Model.Rows[i][2]</td>
<td>#Html.TextBox("Deposit", null, new { placeholder = "Input" })</td>
<td> <input type="submit" value="Deposit" id="btnClick" /></td>
</tr>
count++;
}
</table>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
#section scripts{
<script type="text/javascript">
$(document).ready(function () {
var ProductPack = JSON.stringify({
'Deposit': $("#Deposit").val(),
});
$("#btnClick").click(function () {
var f = {};
f.url = '#Url.Action("InsertDeposit", "Admin")';
f.type = "POST";
f.dataType = "json";
f.data = JSON.stringify({
'Deposit': $("#txtValue").val()
});
f.contentType = "application/json";
f.success = function (response) {
location.reload();
if (response == true) {
window.location.href='Negative';
}
alert("success");
};
f.error = function (response) {
alert("failed");
};
$.ajax(f);
});
});
</script>
}
Controller code:
public JsonResult InsertDeposit(string Deposit, string PartyId, string EmployeId)
{
DataTable dtbl = new DataTable();
int Pid = Convert.ToInt32(PartyId);
using (SqlConnection sqlcon = new SqlConnection(connectionString))
{
sqlcon.Open();
string query = $"Select * from Party where PartyId = #PartyId";
SqlDataAdapter sqlDa = new SqlDataAdapter(query, sqlcon);
sqlDa.SelectCommand.Parameters.AddWithValue("#PartyId", Pid);
sqlDa.Fill(dtbl);
}
return Json(new
{
resut = "OK got it"
});
}
You can serialize the datatable to json by passing it to ASP.NET's Json method:
return Json(dtbl);
But understand that if you call the controller with ajax and get the response in json format, you will have to render that data on the page with client-side script (javascript). You will not be able to use the view template which you have pasted in the question because it is only used on the server side by asp.net.
I don't know why you want to use ajax, but perhaps a better way to do this would be to have a classic html form and submit it on the button click. Then you change your controller to return type IActionResult and the last line to return View(dtbl);. This way you can utilize the view template you have.

A circular reference was detected while serializing an object of type when performing ajax call

On my view, I am using a Viewmodel, and I have a form that has only one textbox that accepts dates (not a part of the viewmodel) and 3 tables. By default on page load.. the tables are populated with data based on today's date (you can see that in the controller code below), but if a user selects a date and clicks the search button then I want the tables data to be changed without a page refresh based on the date they selected.
#using (Html.BeginForm())
{
<div class="form-group mb-3 mt-3" style="margin-right: -1.3%;">
<div class="input-group col-md-3 offset-md-9">
#Html.TextBox("detailsDate", null, new { id = "Details-Date", #class = "form-control datetimepicker" })
<div class="input-group-append">
<button id="Details-Date-Btn" type="submit" class="btn btn-outline-primary"><span class="fa fa-search"></span></button>
</div>
</div>
</div>
}
What I am trying to do is if a user selects and date and hits the search button.. I would like the page to not refresh and the tables data have been changed based on the date. As of right now I am getting:
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.tbl_WeighAssc_8AA7AB5F9DAB261D5142F1D5F5BA6705A588A5AAD2D369FBD4B4BC1BBE0487D4'.
Viewmodel
public class PersonnelDetailsVm
{
private static ConnectionString db = new ConnectionString();
public PersonnelDetailsVm()
{
CurrentWeekDates = new List<DateTime>();
WeighAssociations = new List<tbl_WeighAssc>();
ArrestAssociations = new List<tbl_TEUArrestAssc>();
InspectionAssociations = new List<tblTEUInspectionAssc>();
}
public string IBM { get; set; }
[Display(Name = "Name")]
public string UserName { get; set; }
public bool Active { get; set; }
public List<DateTime> CurrentWeekDates { get; set; }
public List<tbl_WeighAssc> WeighAssociations { get; set; }
public List<tbl_TEUArrestAssc> ArrestAssociations { get; set; }
public List<tblTEUInspectionAssc> InspectionAssociations { get; set; }
public List<code_WeighLocation> WeighLocations => db.code_WeighLocation.ToList();
public List<code_ArrestType> ArrestTypes => db.code_ArrestType.ToList();
public List<code_InspectionLevel> InspectionLevels => db.code_InspectionLevel.ToList();
}
Ajax:
// Submission
//var redirectUrl = '#Url.Action("Index", "Personnels")';
var settings = {};
settings.baseUri = '#Request.ApplicationPath';
var infoGetUrl = "";
if (settings.baseUri === "/AppName") {
infoGetUrl = settings.baseUri + "/Personnels/Details/";
} else {
infoGetUrl = settings.baseUri + "Personnels/Details/";
}
$("#Details-Date-Btn").click(function() {
$.ajax({
url: infoGetUrl,
method: "POST",
data: $("form").serialize(),
success: function(response) {
console.log("success");
$("body").html(response);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});
});
Controller:
public ActionResult Details(string id, string detailsDate)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
tblPersonnel tblPersonnel = db.tblPersonnels.Find(id);
if (tblPersonnel == null)
{
return HttpNotFound();
}
Mapper.Initialize(config => config.CreateMap<tblPersonnel, PersonnelDetailsVm>());
PersonnelDetailsVm person = Mapper.Map<tblPersonnel, PersonnelDetailsVm>(tblPersonnel);
var employeeData = EmployeeData.GetEmployee(person.IBM);
person.UserName =
$"{ConvertRankAbbr.Conversion(employeeData.Rank_Position)} {employeeData.FirstName} {employeeData.LastName}";
if (string.IsNullOrWhiteSpace(detailsDate))
{
var startOfWeek = DateTime.Today.AddDays((int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek -
(int)DateTime.Today.DayOfWeek);
person.CurrentWeekDates = Enumerable.Range(0, 7).Select(i => startOfWeek.AddDays(i)).ToList();
var teuFormIds = db.tbl_TEUForm
.Where(x => person.CurrentWeekDates.Contains(x.EventDate) && x.PersonnelIBM == person.IBM).Select(t => t.Id).ToList();
person.WeighAssociations = db.tbl_WeighAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.ArrestAssociations = db.tbl_TEUArrestAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.InspectionAssociations =
db.tblTEUInspectionAsscs.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
return View(person);
}
else
{
var paramDate = DateTime.ParseExact(detailsDate, "MM/dd/yyyy", CultureInfo.CurrentCulture);
var startOfWeek = paramDate.AddDays((int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek -
(int)paramDate.DayOfWeek);
person.CurrentWeekDates = Enumerable.Range(0, 7).Select(i => startOfWeek.AddDays(i)).ToList();
var teuFormIds = db.tbl_TEUForm
.Where(x => person.CurrentWeekDates.Contains(x.EventDate) && x.PersonnelIBM == person.IBM).Select(t => t.Id).ToList();
person.WeighAssociations = db.tbl_WeighAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.ArrestAssociations = db.tbl_TEUArrestAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.InspectionAssociations =
db.tblTEUInspectionAsscs.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
return Json(person, JsonRequestBehavior.AllowGet);
}
}
So, if the actionresult's paramets detailsDate is not null, then it goes into the else statement which returns a JSON object. When debugging this goes through and when the view is returned I am receiving the error I posted above.
Is there a way to replace the model in the view with what I'm returning from the ajax call so the tables can be based on the right date without a page refresh?
Any help is greatly appreciated.
UPDATE
Based on answer's below I have edited the else statement in my controller method to:
Controller
else
{
var paramDate = DateTime.ParseExact(detailsDate, "MM/dd/yyyy", CultureInfo.CurrentCulture);
var startOfWeek = paramDate.AddDays((int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek -
(int)paramDate.DayOfWeek);
person.CurrentWeekDates = Enumerable.Range(0, 7).Select(i => startOfWeek.AddDays(i)).ToList();
var teuFormIds = db.tbl_TEUForm
.Where(x => person.CurrentWeekDates.Contains(x.EventDate) && x.PersonnelIBM == person.IBM).Select(t => t.Id).ToList();
person.WeighAssociations = db.tbl_WeighAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.ArrestAssociations = db.tbl_TEUArrestAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.InspectionAssociations =
db.tblTEUInspectionAsscs.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
{
PreserveReferencesHandling = PreserveReferencesHandling.All,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
var jsonStr = JsonConvert.SerializeObject(person);
return Json(jsonStr, "text/plain");
}
My jQuery/Ajax is still the same:
$("#Details-Date-Btn").click(function() {
$.ajax({
url: infoGetUrl,
data: $("form").serialize(),
success: function(response) {
console.log("success");
console.log(response);
$("body").html(response);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});
});
But now, when the date is selected I am being returned to a page that shows the Json like a plain text file and losing the HTML and CSS like a normal view.
Here is what I am being returned when a date is selected and the button is clicked.
Also, when I check the console when I select a date and click the button for that date to be sent to the controller I am seeing this:
UPDATE 2
Here is one of my tables.. the other ones are the same setup:
<table class="table table-bordered">
<thead>
<tr>
<th></th>
#foreach (var date in Model.CurrentWeekDates)
{
<th class="text-center">#date.ToString("ddd") <br /> #date.ToShortDateString()</th>
}
<th class="text-center table-success">Total For Week</th>
</tr>
</thead>
<tbody>
#foreach (var weighLocation in Model.WeighLocations)
{
<tr class="text-center">
<td class="table-dark">#weighLocation.Weigh_Location</td>
#foreach (var date in Model.CurrentWeekDates)
{
if (Model.WeighAssociations.Any(x => x.tbl_TEUForm.EventDate == date && x.WeighLocationId == weighLocation.ID))
{
<td>#Model.WeighAssociations.Single(x => x.tbl_TEUForm.EventDate == date && x.WeighLocationId == weighLocation.ID).OccurenceCount</td>
}
else
{
<td>0</td>
}
}
<td class="table-success font-weight-bold">#Model.WeighAssociations.Where(x => x.WeighLocationId == weighLocation.ID).Sum(x => x.OccurenceCount)</td>
</tr>
}
</tbody>
</table>
As far as I can see from your problem, to fix it you can do following steps:
1- View
Add a partial view (_Detail.cshtml)
You need a partial view like _Detail that includes your table like this:
#model PersonnelDetailsVm
<table class="table table-bordered">
<thead>
<tr>
<th></th>
#foreach (var date in Model.CurrentWeekDates)
{
<th class="text-center">#date.ToString("ddd") <br /> #date.ToShortDateString()</th>
}
<th class="text-center table-success">Total For Week</th>
</tr>
</thead>
<tbody>
#foreach (var weighLocation in Model.WeighLocations)
{
<tr class="text-center">
<td class="table-dark">#weighLocation.Weigh_Location</td>
#foreach (var date in Model.CurrentWeekDates)
{
if (Model.WeighAssociations.Any(x => x.tbl_TEUForm.EventDate == date && x.WeighLocationId == weighLocation.ID))
{
<td>#Model.WeighAssociations.Single(x => x.tbl_TEUForm.EventDate == date && x.WeighLocationId == weighLocation.ID).OccurenceCount</td>
}
else
{
<td>0</td>
}
}
<td class="table-success font-weight-bold">#Model.WeighAssociations.Where(x => x.WeighLocationId == weighLocation.ID).Sum(x => x.OccurenceCount)</td>
</tr>
}
</tbody>
</table>
2- Controller
Return the partial view
You should fill the model in your controller and pass it to the partial view.
public ActionResult Details(string id, string detailsDate)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
tblPersonnel tblPersonnel = db.tblPersonnels.Find(id);
if (tblPersonnel == null)
{
return HttpNotFound();
}
Mapper.Initialize(config => config.CreateMap<tblPersonnel, PersonnelDetailsVm>());
PersonnelDetailsVm person = Mapper.Map<tblPersonnel, PersonnelDetailsVm>(tblPersonnel);
var employeeData = EmployeeData.GetEmployee(person.IBM);
person.UserName =
$"{ConvertRankAbbr.Conversion(employeeData.Rank_Position)} {employeeData.FirstName} {employeeData.LastName}";
if (string.IsNullOrWhiteSpace(detailsDate))
{
var startOfWeek = DateTime.Today.AddDays((int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek -
(int)DateTime.Today.DayOfWeek);
person.CurrentWeekDates = Enumerable.Range(0, 7).Select(i => startOfWeek.AddDays(i)).ToList();
var teuFormIds = db.tbl_TEUForm
.Where(x => person.CurrentWeekDates.Contains(x.EventDate) && x.PersonnelIBM == person.IBM).Select(t => t.Id).ToList();
person.WeighAssociations = db.tbl_WeighAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.ArrestAssociations = db.tbl_TEUArrestAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.InspectionAssociations =
db.tblTEUInspectionAsscs.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
// return View(person);
}
else
{
var paramDate = DateTime.ParseExact(detailsDate, "MM/dd/yyyy", CultureInfo.CurrentCulture);
var startOfWeek = paramDate.AddDays((int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek -
(int)paramDate.DayOfWeek);
person.CurrentWeekDates = Enumerable.Range(0, 7).Select(i => startOfWeek.AddDays(i)).ToList();
var teuFormIds = db.tbl_TEUForm
.Where(x => person.CurrentWeekDates.Contains(x.EventDate) && x.PersonnelIBM == person.IBM).Select(t => t.Id).ToList();
person.WeighAssociations = db.tbl_WeighAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.ArrestAssociations = db.tbl_TEUArrestAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.InspectionAssociations =
db.tblTEUInspectionAsscs.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
// return Json(person, JsonRequestBehavior.AllowGet);
}
// return PartialView with the person model
return PartialView("_Detail", person);
}
As you can see in the above code, you should comment the two lines in your code:
// return View(person);
// return Json(person, JsonRequestBehavior.AllowGet);
3- Ajax call
Get the partial view and fill form by it
You don't any changes in ajax call and you can do it like this:
$("#Details-Date-Btn").click(function() {
$.ajax({
url: infoGetUrl,
method: "POST",
data: $("form").serialize(),
success: function(response) {
console.log("success");
$("body").html(response);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});
});
response in this way is a html that comes from partial view and it has all classes as you designed it.
That error message means that one of your child properties refers back to the parent and JSON serialization causes a circular loop.
To fix, replace this:
return Json(person, JsonRequestBehavior.AllowGet);
with this:
return Content(JsonConvert.SerializeObject(person,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
}), "application/json");
You will have to install NewtonSoft.Json:
using Newtonsoft.Json;
A circular reference was detected while serializing an object of type occurred because JSON serializer doesn't support circular references inside your object hierarchy (i.e. passing PersonnelDetailsVm that contains references to data models). To resolve this issue, use JSON.NET's JsonConvert.SerializeObject() with default settings set like this:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.All,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
Afterwards, you can return JsonResult from viewmodel:
string jsonStr = JsonConvert.SerializeObject(person);
return Json(jsonStr);
If you're using IE and encountering save dialog because of friendly JSON errors configuration, you may need to add text/html or text/plain when returning JSON data:
return Json(jsonStr, "text/html");
Or hide the Json() method inside controller class like this:
protected new JsonResult Json(object data)
{
if (!Request.AcceptTypes.Contains("application/json"))
return base.Json(data, "text/plain");
else
return base.Json(data);
}
Additionally, instead of return View(person); you may consider return PartialView("Details", person); because AJAX call intended to stay on same page.
Setting ReferenceLoopHandling = ReferenceLoopHandling.Ignore will handle your issue related to circular reference exception.
Now to about issue(s) you presented in your updates, I think you might have some misunderstanding about how Ajax request work. I think this because when you make an ajax request to server it 'll respond with JSON data which will be representation of your view model and will be agnostic to your view (cshtml) code, so when you call $("body").html(response); you are replacing content of your page with stringified representation of your JSON view model. Take away here is that when you make an ajax request only back-end code will get executed and your view code(cshtml) will not be executed, period.
To solve your you will have to replace content of the table itself and not the body of the page, so you Ajax success callback should be something like:
var tempData = {
"IBM": "IBM",
"UserName": "UserName",
"Active": false,
"CurrentWeekDates": [],
"WeighAssociations": [],
"ArrestAssociations": [],
"InspectionAssociations": [],
"WeighLocations": [],
"ArrestTypes": [],
"InspectionLevels": []
};
function onSuccess(response){
var table = $("#tblData");
table.html("");
// code to create your head same code as your cshtml
table.append("<thead><th>New Column</th></thead>");
table.append("<tr><td>Column 1</td></tr>");
$("#btnLoad").text("Loaded");
}
$("#btnLoad").click(function(){
$("#btnLoad").attr("disabled", "");
$("#btnLoad").text("Loading...");
// call onSuccess function after 5 second to replicate server call
setTimeout(function(){ onSuccess(tempData) }, 5000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btnLoad">Load Data</button>
<table id="tblData" class="table table-bordered">
<thead>
<tr>
<th></th>
<th class="text-center">Mon<br /> 01-01-1990</th>
<th class="text-center table-success">Total For Week</th>
</tr>
</thead>
<tbody>
<tr class="text-center">
<td class="table-dark">Column 1</td>
<td>Columns 2</td>
<td>0</td>
<td class="table-success font-weight-bold">0</td>
</tr>
</tbody>
</table>
I hope this helps you!
You have 2 different return methods and you're setting the body content to the response of the request, which if the else statement is run will be JSON and not html.
I would suggest to either always return JSON or always return a View/Partial.
else
{
var paramDate = DateTime.ParseExact(detailsDate, "MM/dd/yyyy", CultureInfo.CurrentCulture);
var startOfWeek = paramDate.AddDays((int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek -
(int)paramDate.DayOfWeek);
person.CurrentWeekDates = Enumerable.Range(0, 7).Select(i => startOfWeek.AddDays(i)).ToList();
var teuFormIds = db.tbl_TEUForm
.Where(x => person.CurrentWeekDates.Contains(x.EventDate) && x.PersonnelIBM == person.IBM).Select(t => t.Id).ToList();
person.WeighAssociations = db.tbl_WeighAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.ArrestAssociations = db.tbl_TEUArrestAssc.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
person.InspectionAssociations =
db.tblTEUInspectionAsscs.Where(x => teuFormIds.Contains(x.TEUId)).ToList();
JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
{
PreserveReferencesHandling = PreserveReferencesHandling.All,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
var jsonStr = JsonConvert.SerializeObject(person);
//return Json(jsonStr, "text/plain");
return Partial(person);
}
I would suggest the below steps
One partial view for filters which include DateTime and Submit button(FilterPartial)
One Partial view for tables to be rendered(ResultsPartial)
When the body is loaded then load the first partial view(let's call FilterPartial) which will set the values in the ResultsPartial view.
function GetData(params) {
$.ajax({
type: "POST",
url: '/controller/Action',
data: {
//Parameters
},
dataType: 'html',
success: function (data) {
//You can either load the html directly or render the control here
}
});
}
public PartialViewResult Action()
{
return PartialView("");
}
The ViewModel logic can be kept as it is, you have to segregate the views.
Let me know if this helps...
You need to create two methods, first one to return the view with ActionResult return type:
public ActionResult Details(string id, string detailsDate)
{
....
return View(person);
}
And a second method which will be called via Ajax to return the Json data with JsonResult type
public JsonResult GetData(string id, string detailsDate)
{
....
return Json(person, JsonRequestBehavior.AllowGet);
}
To prevent repeating same getting data logic twice, you can move all data logic to the Json method and keep View method return with no data, then just trigger Ajax call when page load is completed to get initial data from Json method.

Pass data from controller to view via JSONResult

I'd like to send ViewModel from controller to view in JSON format.
Controller:
public ActionResult Select(int pageLimiter)
{
var viewModel = new ArticlesViewModel
{
Articles = this.Service.GetArticles(0, 0, 0),
ArticlesTotal = this.Service.CountArticles(0),
Pages = new List<string>
{
"1", "2", "3"
}
};
return Json(viewModel, JsonRequestBehavior.AllowGet);
}
View:
<ul class="articleList">
#if (#Model != null)
{
foreach (var article in #Model.Articles)
{
<li>
<header>#article.Title</header>
<nav>
<span>#article.AuthorName</span> |
<time>#article.PublishDate.ToString("")</time> |
<span>#article.CategoryName</span> |
<span>#article.Comments Comments</span>
</nav>
<section>
#article.Content
</section>
</li>
}
}
</ul>
<script type="text/javascript">
$(document).ready(function () {
GetArticles(5);
$("#selectPager").change(function () {
var selectedItem = "";
$("#selectPager option:selected").each(function () {
selectedItem = $(this).text();
});
GetArticles(selectedItem);
});
});
function GetArticles(pageLimitValue) {
$.ajax(
{
url: "/Articles/Select",
dataType: "json",
data: { pageLimiter: pageLimitValue },
async: true,
beforeSend: function () {
alert("before");
},
complete: function (data) {
#Model = SOME_MAGIC_TRICKS
}
});
}
As you can see, in the complete event are words SOME_MAGIC_TRICKS. In this place I'd like to set #Model obtained from controller. Is it possible at all? How to insert data from ajax result to view model (it's null by default)?
You are trying to modify server variable from client's code. It's not possible.
If you want to re-render your page's content on complete, you may render <ul class="articleList"> with PartialView and return same partial view instead of JsonResult. Further, oncomplete handler will update your <ul class="articleList"> with returned content.
You can send data doing serialize it may be like:
public ActionResult Select(int pageLimiter)
{
var viewModel = new ArticlesViewModel
{
Articles = this.Service.GetArticles(0, 0, 0),
ArticlesTotal = this.Service.CountArticles(0),
Pages = new List<string>
{
"1", "2", "3"
}
};
string myjsonmodel = new JavaScriptSerializer().Serialize(viewModel );
return Json(jsonmodel = viewModel, JsonRequestBehavior.AllowGet);
}
dont forget using using System.Web.Script.Serialization;
Edit:
To deserialize object try this:
#{
JavaScriptSerializer jss= new JavaScriptSerializer();
User user = jss.Deserialize<User>(jsonResponse);
}

how to return multiple variables with jsonresult asp.net mvc3

How to return multiple variables on JsonResult method
for example i want to return this two variables:
string result = "Successed";
string ID = "32"
I know how to return only one string:
return Json("Inserted");
public ActionResult YourAction()
{
var result=new { Result="Successed", ID="32"};
return Json(result, JsonRequestBehavior.AllowGet);
}
EDIT : As per the comment "How to get this data in client"
You can use getJSON from view to get this data like this
$(function(){
$.getJSON('YourController/YourAction', function(data) {
alert(data.Result);
alert(data.ID);
});
});
Make sure you have jQuery loaded in your view for this code to work.
Return an anonymous object.
return Json( new { Result = result, Id = ID } );
I normally do something like this:
public enum NoticeTypes
{
Default,
UpdateComplete,
ResponsePending,
Notice,
Error,
Redirect,
WaitAndRetryAttempt
}
public class AjaxJsonResponse
{
public UserNotice Notice { get; set; }
public object Data { get; set; }
private AjaxJsonResponse() { }
public static JsonResult Create(UserNotice Notice,object Data)
{
return new JsonResult()
{
Data = new
{
Notice = Notice,
Data = Data
}
};
}
}
So that I can write my javascript to always expect ajax calls to return data in a certain format.
return AjaxResponse.Create(NoticeTypes.UpdateComplete, new
{
Result = result,
Id = ID
});
Now you can do things like an Ajax Complete global handler that can intercept things like Redirect or WaitAndRetry before the normal handler gets it, and to have a standard way of communicating additional information about the returned data that is the same across your application.
On your controller use something like this:
var result = new { data= stuff, data2 = otherstuff };
return Json(result, JsonRequestBehavior.AllowGet);
If you are using .ajax() on your JavaScript you can use your data acessing like this:
$.ajax(
{
url: '/Controller/Method/',
type: 'POST',
data: 'data=' + data,
success: function (result) {
$('#id').html("");
$(result.data).appendTo('#id');
$('#id2').html("");
$(result.data2).appendTo('#id2');
$('#id').show();
$('#id2').show();
}
});
1. Return as collection inside anonymous type
This is the java script/ajax call and the complete html.
< script type = "text/javascript" >
$(document).ready(function() {
$("#ddlProduct").hide();
$("#ddlRegion").change(function() {
$("#ddlProduct").show();
$("#ddlProduct").empty();
$.ajax({
type: "Post",
url: "#Url.Action("
GetProducts ")",
dataType: "Json",
data: {
id: $("#ddlRegion").val()
},
success: function(jsonData) {
console.log($(jsonData).length);
if ($(jsonData.ProductList).length == 0) {
$("#divProduct").hide();
} else {
$("#divProduct").show();
}
$.each(jsonData.ProductList, function(i, Product) {
$("#ddlProduct").append('<option value=" ' + Product.Value + ' ">' + Product.Text + '</option>');
});
if ($(jsonData.FlavourList).length == 0) {
$("#divFlavour").hide();
} else {
$("#divFlavour").show();
$.each(jsonData.FlavourList, function(i, flavour) {
$("#ddlFlavour").append('<option value=" ' + flavour.Value + ' ">' + flavour.Text + '</option>');
});
}
},
error: function(ex) {
alert("Failed to return Products <br/>");
}
});
return false;
})
}); //Document Ready Ends
< /script>
#{ ViewBag.Title = "Products Drop Down Demo"; }
<h2>Products Drop Down Demo</h2>
#using (Html.BeginForm()) {
<div>#Html.Label("Select Region:")</div>
<div class="editor-field">
#if (ViewData.ContainsKey("Region")) { #Html.DropDownList("ddlRegion", ViewData["Region"] as List
<SelectListItem>) }
</div>
<div id="divProduct" hidden="hidden">
<br />
<div>
Select a Product:
</div>
<div>
#Html.DropDownList("ddlProduct", new SelectList(string.Empty, "Value", "Text"), "Please select a Product", new { style = "width:250px", #class = "dropdown1" })
</div>
</div>
<div id="divFlavour" hidden="hidden">
<div>
<br />Select a Flavour:
</div>
<div>
#Html.DropDownList("ddlFlavour", new SelectList(string.Empty, "Value", "Text"), "Please select a Flavour", new { style = "width:250px", #class = "dropdown1" })
</div>
</div>
}
This is the controller action that returns the data
I tested and it is working.
public ActionResult LoadRegion()
{
List<SelectListItem> Regions = new List<SelectListItem>();
Regions.Add(new SelectListItem { Text = "Select A Region", Value = "0" });
Regions.Add(new SelectListItem { Text = "Asea", Value = "1" });
Regions.Add(new SelectListItem { Text = "Australia", Value = "4" });
Regions.Add(new SelectListItem { Text = "America", Value = "5" });
Regions.Add(new SelectListItem { Text = "Europe", Value = "6" });
ViewData["Region"] = Regions;
return View();
}
public JsonResult GetProducts(string id)
{
List products = new List();
List flavours = new List();
products.Add(new SelectListItem { Text = "Select Product", Value = "0" });
products.Add(new SelectListItem { Text = "Cheese", Value = "1" });
products.Add(new SelectListItem { Text = "Sause", Value = "2" });
products.Add(new SelectListItem { Text = "Veberage", Value = "3" });
products.Add(new SelectListItem { Text = "Snacks", Value = "4" });
flavours.Add(new SelectListItem { Text = "Select Flavour", Value = "0", Selected = true });
flavours.Add(new SelectListItem { Text = "Sweet", Value = "1" });
flavours.Add(new SelectListItem { Text = "Sour", Value = "2" });
flavours.Add(new SelectListItem { Text = "Spicy", Value = "3" });
var myResult = new
{
ProductList = products,
FlavourList = flavours
};
return Json(myResult, JsonRequestBehavior.AllowGet);
}
Let me know if you have any issue running this code.
Thanks
Premjeet
You should return an object with multiple properties:
return Json(new {
result,
ID
});
The JSON serializer will convert C# anonymous types into JSON object literals.
In Action method :
Using new keywork
var genericResult = new { homeworkData = homework, attachmentData = homeworkAttachment };
var result = this.Json(genericResult, JsonRequestBehavior.AllowGet);
return result;
In jquery side :
function getHomewrokDetailResponse(dataSent, result) {
if (result && result.homeworkData) {
homeworkId = result.homeworkData.DASH_EMPLOYEE_HOMEWORK_ID;
....
}

How to populate a #html.dropdownlist mvc helper using JSon

I have a <select> which is loaded by a JSon. But I want to use "#html.dropdownlist helper" instead. My Json is:
function LoadSites() {
$("SelectSite").html("");
$.getJSON("/Pedido/GetSite", null, function (data) {
$("#SelectSite").append("<option value=0>Selecione...</option>");
$.each(data.Result, function (index, site) {
$("#SelectSite").append("<option value='" + site.Id + "'>" + site.Nome + "</option>");
});
});
this Json populate this...
<select id="SelectSite"></select>
My Controller:
[HttpGet]
public JsonResult GetSite()
{
Repository<Site> siteRepo = new Repository<Site>( unitOfWork.Session );
return this.Json( new { Result = siteRepo.All() }, JsonRequestBehavior.AllowGet );
}
I want my code more reusable and self-documenting.
How can I send the object "site" from JSon to "cshtml" using dropdownlist to do something like #html.dropdownlist(site.id, site.Nome)???
Is there a way?
Tks guys.
In your view:
#Html.DropDownListFor(x => x.SiteId, new SelectList(Enumerable.Empty<SelectListItem>()))
where SiteId is a property of your view model which will receive the selected site id when the form is submitted.
and then you could populate this dropdown using AJAX:
$(function() {
$.getJSON('#Url.Action("GetSite", "Pedido")', function(result) {
var ddl = $('#SiteId');
ddl.empty();
$(result).each(function() {
ddl.append(
$('<option/>', {
value: this.Id
}).html(this.Nome)
);
});
});
});
and the controller action that would return the JSON data:
public ActionResult GetSite()
{
var sites = new[]
{
new { Id = "1", Nome = "site 1" },
new { Id = "2", Nome = "site 3" },
new { Id = "3", Nome = "site 3" },
};
return Json(sites, JsonRequestBehavior.AllowGet);
}