MVC.NET old data comes back after refresh of screen - asp.net-mvc

I have created jquery ajax call in my view page and this successfully posts data.
However, if I press ctrl+F5 to force browser refresh, old data comes back.
If I close down browser and revisit the site, it now shows updated data.
Following is my action in controller.
I am fairly new to MVC.NET and I am sure there is something I am missing.
Can you please advise?
I truly appreciate in advance.
[HttpPost]
[ActionName("EditCategory")]
public ActionResult EditCategory(miniCateObj[] items)
{
int id = int.Parse(items[0].id.Replace("'",""));
string newName = items[0].cateName.Replace("'", "");
ModelState.Remove("CategoryName");
ModelState.Clear();
Category model = _categoryService.GetCategoryByCategoryId( id);
model.CategoryName = newName;
_categoryService.UpdateCategorySite(model);
return View(model);
}
And following is the ajax call I'm using
$.ajax({
type: "POST",
url: '#Url.Action("EditCategory", "CloSite")',
contentType: "application/json; charset=utf-8",
data: JSON.stringify({
"items": [{
"id": "'" + id + "'",
"cateName": "'" + obj.val() + "'"
}]
}),
dataType: "application/xml-urlencode",
success: function () {
alert('Success');
},
error: function (xhr, textStatus, error) {
console.log(xhr.statusText);
console.log(textStatus);
console.log(error);
}
});
Also, I'm not using ORM / Entity Framework. I had problem the projects .savechanges() not updating(in Entity Framework), so I ended up writing direct SQL to update as following,
public int UpdateByCategoryId(int categoryId, string cateName) {
using(var connection = this.Context.Database.Connection) {
if (string.IsNullOrEmpty(connection.ConnectionString)) connection.ConnectionString = ConfigurationHelper.ConnectionString;
var query = string.Format(#"UPDATE Categories set CategoryName = '{0}' where Id = {1}", cateName, categoryId);
return connection.Execute(query);
}
}

Related

Razor MVC calling Action from JavaScript

I'm trying to call an Action from javascript with Ajax but when i publish the site the request returns me a 302 error
this is the javascript call
$("#buyButton").click(function () {
$.ajax({
type: "POST",
url: "/TessileCart/Buy?offerType=" + '#ViewBag.offerType' + "&requestPath=" + '#ViewBag.requestPath' + "&currency=" + currentCurrency,
contentType: "application/json; charset=utf-8",
dataType: "json",
data: ({
}),
error: function (data) {
},
success: function (data) {
window.location = '/'
}
});
});
and this is the Action server side
public ActionResult Buy(string offerType, string requestPath, string currency)
{
try
{
decimal codStore = Convert.ToDecimal(HttpContext.Session[Global.CodStore]);
string userName = HttpContext.Session[Global.UserName].ToString();
cartRep.CheckOut(codStore, userName, System.Web.HttpContext.Current, currency);
return RedirectToAction("Index", "Home", new { offerType = offerType });
}
catch (Exception ex)
{
Global.log.WriteLog(this.GetType().Name, "Buy", "", ex, Session[Global.UserName].ToString());
return RedirectToAction("Index", "Cart", new { offerType = offerType, requestPath = requestPath, error = Global.ErrorMex });
}
}
can someone explain me how to resolve?
Thanks,
Federico
You are calling a post method, but using the get method way.
the url should stop until /buy
url: "/TessileCart/Buy",
before that build the post parameter, before the $.ajax call:
let senddata = {
offerType: #ViewBag.offerType,
requestPath: #ViewBag.requestType,
currency: currentCurrency
}
the rest of parameter, send it as json as input to data
data: JSON.stringify(senddata),
and last decorated your action with HttpPost
[HttpPost]
public ActionResult Buy(...)

Passing IEnumerable through Json

I'm making a "Like" button in a simple comment database MVC program.
I'm passins the ID of the comment through to a ActionResult in the HomeController when I hover over the "Like" button. The problem (I think) is that I don't know how to pass the IEnumerable list of Likes to the ajax.
The script and HTML part:
HTML:
Like this
Script:
$(".likes").hover(function (event) {
var Liker = { "CID": event.target.id };
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/Home/ShowLike/",
data: JSON.stringify(Liker),
dataType: "json",
success: function (data) {
$.each(data.Name, function (value) {
alert(value);
});
},
error: function (xhr, err) {
// Note: just for debugging purposes!
alert("readyState: " + xhr.readyState +
"\nstatus: " + xhr.status);
alert("responseText: " + xhr.responseText);
}
});
});
HomeController -> ShowLike
[HttpPost]
public ActionResult ShowLike(Liker ids)
{
LikesRepository lkrep = new LikesRepository();
IEnumerable<Like> list = lkrep.GetLikes(ids.CID);
return Json(list);
}
LikesRepository
public class LikesRepository
{
CommentDBDataContext m_db = new CommentDBDataContext();
public IEnumerable<Like> GetLikes(int iden)
{
var result = from c in m_db.Likes
where c.CID == iden
orderby c.Name ascending
select c;
return result;
}
public void AddLike(Like c)
{
m_db.Likes.InsertOnSubmit(c);
m_db.SubmitChanges(); //This works
}
}
After diving into the problem more, we found it was actually triggering an internal server error (500). This was caused by a circular reference from serializing the LINQ to SQL objects to JSON. This issue is discussed several times...
How to remove circular reference in Entity Framework?
How did I solve the Json serializing circular reference error?
Circular Reference exception with JSON Serialisation with MVC3 and EF4 CTP5w
An alternate solution is to return the data as lists of strings as they only required the names.

How to submit local jqgrid data and form input elements

Page contains single form with input elements and jqgrid data.
jqGrid data is retrieved in json using loadonce: true option.
Data is edited locally.
How to submit all this data if submit button is pressed?
Has jqGrid any method which can help to submit all data from all rows. jqGrid - How to edit and save multiple rows at once? mentions that jQuery ajax form plugin should be used but I havent found any sample.
jqGrid probably holds retrieved json table in element. In this case form plugin is not capable read this data.
How to get and submit all data retrieved using loadonce: true and edited?
Update1
Based on Oleg answer I tried:
function SaveDocument() {
var gridData = $("#grid").jqGrid('getGridParam','data');
var postData = JSON.stringify(gridData);
$('#_detail').val( postData );
var res = $("#Form").serializeArray();
$.ajax({ type: "POST",
url: 'Edit'
data : res
});
}
}
aspx page:
<form id="Form" class='form-fields'>
.... other form fields
<input name='_detail' id='_detail' type='hidden' />
</form>
<div id="grid1container" style="width: 100%">
<table id="grid">
</table>
</div>
In ASP.NET MVC2 Controller Edit method I tried to parse result using
public JsonResult Edit(string _detail) {
var order = new Order();
UpdateModel(order, new HtmlDecodeValueProviderFromLocalizedData(ControllerContext));
var serializer = new JavaScriptSerializer();
var details = serializer.Deserialize<List<OrderDetails>>>(_detail);
}
Exception occurs in Deserialize() call. Decimal and date properties are passed in localized format but it looks like Deserialize() does not parse
localized strings and there is no way to force it to use converter like HtmlDecodeValueProviderFromLocalizedData passed to UpdateModel.
How to fix ?
Is is reasonable/how to convert _detail parameter into NameValue collection and then use UpdateModel to update details, use some other deserialize or other idea ?
Update 2.
Decimal and Date CurrentUICulture values are present in form and in jqGrid data. Sample provided handles them in form OK but fails for jqGrid data.
This controller should handle different entity types, form fields and jqgrid columns can defined at runtime. So using hard-coded names is not possible.
Based on Oleg reply I tried to override decimal conversion by creating converter
public class LocalizedTypeConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get
{
return new ReadOnlyCollection<Type>(new Type[] { typeof(decimal) });
}
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type,
JavaScriptSerializer serializer)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
if (type == typeof(decimal))
return decimal.Parse(dictionary["resources"].ToString(), CultureInfo.CurrentCulture);
return null;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
throw new InvalidOperationException("We only Deserialize");
}
}
But conversion still causes exception
0,0000 is not valid value for decimal. It looks like decimal converter cannot overridden. How to fix ?
First of all you can get all local data from the jqGrid with respect of
var localGridData = $("#list").jqGrid('getGridParam','data');
If you will need to send only subset of rows of the grid, like the selected rows only, you can need to get _index:
var idsToDataIndex = $("#list").jqGrid('getGridParam','_index');
To send the data to the server you can use the following function for example
var sendData = function(data) {
var dataToSend = JSON.stringify(data);
alert("The following data are sending to the server:\n" + dataToSend);
$.ajax({
type: "POST",
url: "yourServerUrl",
dataType:"json",
data: dataToSend,
contentType: "application/json; charset=utf-8",
success: function(response, textStatus, jqXHR) {
// display an success message if needed
alert("success");
},
error: function(jqXHR, textStatus, errorThrown) {
// display an error message in any way
alert("error");
}
});
};
In the demo you will find a little more sophisticated example having two buttons: "Send all grid contain", "Send selected rows". The corresponding code is below
$("#sendAll").click(function(){
var localGridData = grid.jqGrid('getGridParam','data');
sendData(localGridData);
});
$("#sendSelected").click(function(){
var localGridData = grid.jqGrid('getGridParam','data'),
idsToDataIndex = grid.jqGrid('getGridParam','_index'),
selRows = grid.jqGrid('getGridParam','selarrrow'),
dataToSend = [], i, l=selRows.length;
for (i=0; i<l; i++) {
dataToSend.push(localGridData[idsToDataIndex[selRows[i]]]);
}
sendData(dataToSend);
});
where
var grid = $("#list"),
decodeErrorMessage = function(jqXHR, textStatus, errorThrown) {
var html, errorInfo, i, errorText = textStatus + '\n<br />' + errorThrown;
if (jqXHR.responseText.charAt(0) === '[') {
try {
errorInfo = $.parseJSON(jqXHR.responseText);
errorText = "";
for (i=0; i<errorInfo.length; i++) {
if (errorText.length !== 0) {
errorText += "<hr/>";
}
errorText += errorInfo[i].Source + ": " + errorInfo[i].Message;
}
}
catch (e) { }
} else {
html = /<body.*?>([\s\S]*)<\/body>/i.exec(jqXHR.responseText);
if (html !== null && html.length > 1) {
errorText = html[1];
}
}
return errorText;
},
sendData = function(data) {
var dataToSend = JSON.stringify(data);
alert("The following data are sending to the server:\n"+dataToSend);
$.ajax({
type: "POST",
url: "yourServerUrl",
dataType:"json",
data: dataToSend,
contentType: "application/json; charset=utf-8",
success: function(response, textStatus, jqXHR) {
// remove error div if exist
$('#' + grid[0].id + '_err').remove();
alert("success");
},
error: function(jqXHR, textStatus, errorThrown) {
// remove error div if exist
$('#' + grid[0].id + '_err').remove();
// insert div with the error description before the grid
grid.closest('div.ui-jqgrid').before(
'<div id="' + grid[0].id + '_err" style="max-width:' + grid[0].style.width +
';"><div class="ui-state-error ui-corner-all" style="padding:0.7em;float:left;"><span class="ui-icon ui-icon-alert" ' +
'style="float:left; margin-right: .3em;"></span><span style="clear:left">' +
decodeErrorMessage(jqXHR, textStatus, errorThrown) + '</span></div><div style="clear:left"/></div>');
}
});
};
I think, that more difficult and more complex problem you will become on the server. In case of concurrency errors, but I wrote you about the problems before. Exactly because of the problems I personally would never implement saving of multiple rows on the server.
UPDATED: To get data from the form you can use jQuery.serialize. You should use name attribute for all fields in the form which you want to serialize. All data which you need to send are
var allData = {
localGridData: grid.jqGrid('getGridParam','data'),
formData: $("#formid").serialize()
};
You can send the data exactly like I described before: sendData(allData).

How can I RedirectToAction within $.ajax callback?

I use $.ajax() to poll an action method every 5 seconds as follows:
$.ajax({
type: 'GET', url: '/MyController/IsReady/1',
dataType: 'json', success: function (xhr_data) {
if (xhr_data.active == 'pending') {
setTimeout(function () { ajaxRequest(); }, 5000);
}
}
});
and the ActionResult action:
public ActionResult IsReady(int id)
{
if(true)
{
return RedirectToAction("AnotherAction");
}
return Json("pending");
}
I had to change the action return type to ActionResult in order to use RedirectToAction (originally it was JsonResult and I was returning Json(new { active = 'active' };), but it looks to have trouble redirecting and rendering the new View from within the $.ajax() success callback. I need to redirect to "AnotherAction" from within this polling ajax postback. Firebug's response is the View from "AnotherAction", but it's not rendering.
You need to consume the result of your ajax request and use that to run javascript to manually update window.location yourself. For example, something like:
// Your ajax callback:
function(result) {
if (result.redirectUrl != null) {
window.location = result.redirectUrl;
}
}
Where "result" is the argument passed to you by jQuery's ajax method after completion of the ajax request. (And to generate the URL itself, use UrlHelper.GenerateUrl, which is an MVC helper that creates URLs based off of actions/controllers/etc.)
I know this is a super old article but after scouring the web this was still the top answer on Google, and I ended up using a different solution. If you want to use a pure RedirectToAction this works as well. The RedirectToAction response contains the complete markup for the view.
C#:
return RedirectToAction("Action", "Controller", new { myRouteValue = foo});
JS:
$.ajax({
type: "POST",
url: "./PostController/PostAction",
data: data,
contentType: "application/json; charset=utf-8",
dataType: "json",
complete: function (result) {
if (result.responseText) {
$('body').html(result.responseText);
}
}
});
C# worked well
I just changed the JS because responseText was not working for me:
$.ajax({
type: "POST",
url: posturl,
contentType: false,
processData: false,
async: false,
data: requestjson,
success: function(result) {
if (result) {
$('body').html(result);
}
},
error: function (xhr, status, p3, p4){
var err = "Error " + " " + status + " " + p3 + " " + p4;
if (xhr.responseText && xhr.responseText[0] == "{")
err = JSON.parse(xhr.responseText).Message;
console.log(err);
}
});
You could use the Html.RenderAction helper in a View:
public ActionResult IsReady(int id)
{
if(true)
{
ViewBag.Action = "AnotherAction";
return PartialView("_AjaxRedirect");
}
return Json("pending");
}
And in the "_AjaxRedirect" partial view:
#{
string action = ViewBag.ActionName;
Html.RenderAction(action);
}
Reference:
https://stackoverflow.com/a/49137153/150342

Deleting multiple records in ASP.NET MVC using jqGrid

How can you enable multiple selection in a jqGrid, and also allow users to delete all of the selected rows using an ASP.NET MVC controller?
I have set the delete url property to my /Controller/Delete method, and this works fine if one record is selected. However, if multiple records are selected, it attempts to send a null value back to the controller where an integer id is required.
You can, but you have to write code for it:
deleteSelected: function(grid) {
if (!grid.jqGrid) {
if (console) {
console.error("'grid' argument must be a jqGrid");
}
return;
}
var ids = grid.getGridParam('selarrrow');
var count = ids.length;
if (count == 0) return;
if (confirm("Delete these " + count + " records?")) {
$.post("DeleteMultiple",
{ ids: ids },
function() { grid.trigger("reloadGrid") },
"json");
}
}
[HttpPost]
public ActionResult DeleteMultiple(IEnumerable<Guid> ids)
{
if (!Request.IsAjaxRequest())
{
// we only support this via AJAX for now.
throw new InvalidOperationException();
}
if (!ids.Any())
{
// JsonError is an internal class which works with our Ajax error handling
return JsonError(null, "Cannot delete, because no records selected.");
}
var trans = Repository.StartTransaction();
foreach (var id in ids)
{
Repository.Delete(id);
}
trans.Commit();
return Json(true);
}
I want to update this for MVC2 and jquery 1.4.2, if you want to pass array parameters to mvc2:
var ids = $("#grid").getGridParam('selarrrow');
var postData = { values: ids };
if (confirm("Delete these " + count + " records?")) {
$.ajax({
type: "POST",
traditional: true,
url: "GridDBDemoDataDeleteMultiple",
data: postData,
dataType: "json",
success: function() { $("#grid").trigger("reloadGrid") }
});
}
check http://jquery14.com/day-01/jquery-14 ajax part
thx

Resources