How can I send 2 parameters in data-ajax-success? - ajax

I write code that will be deleted from the product database. For this I need to perform in ajax that if the operation was performed then it will also delete the row in the table on the page.
the code behind -
public IActionResult OnPost (int id)
{
try
{
Order order = Order.Where (a => a.Id == id) .FirstOrDefault ();
_context.Order.Remove (order);
_context.SaveChanges ();
JsonType returnJson = new JsonType {Status = 0, Massage = "success"};
return new JsonResult (returnJson);
}
catch
{
JsonType returnJson = new JsonType {Status = 1, Massage = "canceled"};
return new JsonResult (returnJson);
}
}
The code on the page-
<form method = "post" asp-route-id = "# item.Id" data-ajax = "true" data-ajax-confirm = "Are you sure?" data-ajax-success = "deleteItem (this)">
<input type = "submit" value = "delete" asp-route-id = "# item.Id" class = "dropdown-item" />
</form>
And the javascript code
function deleteItem (form) {
$ (form) .parent (). parent (). css ({
"display": "none"
});
}
The problem when the file fails, it also deletes the row in the table.
So I thought of getting the response.
function deleteItem (response) {
// if response ...
}
But then I write the code on the page like this -
<form .... data-ajax-success = "deleteItem">
....
</form>
And I can not get both data at the same time,
How can this be done?

Try this
<form method = "post" asp-route-id = "#
item.Id" data-ajax = "true"
data-ajax-confirm = "Are you sure?"
data-ajax-success = "deleteItem">
<input type = "submit" value = "delete" asp-route-id = "# item.Id" class = "dropdown-item" />
</form>
var deleteItem= function(context){
console.log(context);
};

Related

Ajax Login from MVC

I have an MVC project that uses the inbuilt forms authentication (which talks to the MDF database stored in App_data). I want to change the login form to be the Ajax login form so that I can take advantage of the "onSuccess" and "onFailure" options.
Does anyone have a working example of how I would achive this as I've tried previuosly but I can't get the form to authenticate it just does nothing. I think I may have missed a step so any help is appreciated.
Example code would also be benificial. Please find my current code below.
The login view
#model MyProject.Models.LoginViewModel
#using (Ajax.BeginForm("Login", "Account", null, new AjaxOptions
{
OnSuccess = "OnSuccess",
OnBegin = "OnBegin",
OnFailure = "OnFailure",
OnComplete = "OnComplete",
HttpMethod = "POST",
UpdateTargetId = "target"
}))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Login Form</legend>
<ol>
<li>
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName)
#Html.ValidationMessageFor(m => m.UserName)
</li>
<li>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password)
#Html.ValidationMessageFor(m => m.Password)
</li>
<li>
#Html.CheckBoxFor(m => m.RememberMe)
#Html.LabelFor(m => m.RememberMe, new { #class = "checkbox" })
</li>
</ol>
<input type="submit" value="Login" />
</fieldset>
}
Here is the login controller
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public JsonResult ValidateUser(string userid, string password,
bool rememberme)
{
LoginStatus status = new LoginStatus();
if (Membership.ValidateUser(userid, password))
{
FormsAuthentication.SetAuthCookie(userid, rememberme);
status.Success = true;
status.TargetURL = FormsAuthentication.
GetRedirectUrl(userid, rememberme);
if (string.IsNullOrEmpty(status.TargetURL))
{
status.TargetURL = FormsAuthentication.DefaultUrl;
}
status.Message = "Login attempt successful!";
}
else
{
status.Success = false;
status.Message = "Invalid UserID or Password!";
status.TargetURL = FormsAuthentication.LoginUrl;
}
return Json(status);
}
Here is the login view model
public class LoginStatus
{
public bool Success { get; set; }
public string Message { get; set; }
public string TargetURL { get; set; }
}
Script on the page for handling the form
$(document).ready(function () {
$("#login").click(function () {
$("#message").html("Logging in...");
var data = {
"UserName": $("#userid").val(),
"Password": $("#password").val(),
"RememberMe": $("#rememberme").prop("checked")
};
$.ajax({
url: "/Home/Index",
type: "POST",
data: JSON.stringify(data),
dataType: "json",
contentType: "application/json",
success: function (status) {
$("#message").html(status.Message);
if (status.Success)
{
window.location.href = status.TargetURL;
}
},
error: function () {
$("#message").html("Error while authenticating user credentials!");
}
});
});
});
I've an extensions (MvcNotification) that put into ViewData or TempData messages to display.
To complement this, my post actions return "ERROR" or "OK" and i use those messages inside the ajax form OnSuccess.
MessageType
public enum MessageType
{
Success,
Warning,
Error,
Info
}
AjaxMessagesFilter
/// <summary>
/// If we're dealing with ajax requests, any message that is in the view data goes to the http header.
/// </summary>
public class AjaxMessagesFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
var viewData = filterContext.Controller.ViewData;
var response = filterContext.HttpContext.Response;
foreach (var messageType in Enum.GetNames(typeof(MessageType)))
{
var message = viewData.ContainsKey(messageType)
? viewData[messageType]
: null;
if (message != null) // We store only one message in the http header. First message that comes wins.
{
response.AddHeader("X-Message-Type", messageType.ToLower());
response.AddHeader("X-Message", HttpUtility.HtmlEncode(message.ToString()));
return;
}
}
}
}
}
ControllerExtensions
public static class ControllerExtensions
{
public static ActionResult ShowMessage(this Controller controller, MessageType messageType, string message, bool showAfterRedirect = false, bool UseJson = false)
{
var messageTypeKey = messageType.ToString();
if (showAfterRedirect)
{
controller.TempData[messageTypeKey] = message;
}
else
{
controller.ViewData[messageTypeKey] = message;
}
if (UseJson)
return new JsonResult() { Data = "ERROR", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
else
return new ContentResult() { Content = "ERROR" };
}
public static ActionResult ShowMessage(this ControllerBase controller, MessageType messageType, string message, bool showAfterRedirect = false, bool UseJson = false)
{
var messageTypeKey = messageType.ToString();
if (showAfterRedirect)
{
controller.TempData[messageTypeKey] = message;
}
else
{
controller.ViewData[messageTypeKey] = message;
}
if (UseJson)
return new JsonResult() { Data = "ERROR", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
else
return new ContentResult() { Content = "ERROR" };
}
public static ActionResult EmptyField(this Controller controller, string FieldName, bool IsJson = false)
{
controller.ShowMessage(MessageType.Info, String.Format("O campo \"{0}\" é de carácter obrigatório.", FieldName));
return IsJson == false ? (ActionResult)new ContentResult() { Content = "ERROR" } : (ActionResult)new JsonResult() { Data = "ERROR", JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
To call the extension inside the controller:
this.ShowMessage(MessageType.Error, "An error has occurred");
if you want to redirect after the message is thrown, you need to add true in the last parameter.
this.ShowMessage(MessageType.Error, "An error has occurred", true);
Note: I created the EmptyField method to give a standart message when some field is empty.
Action Example (LoginPost)
[HttpPost]
[AllowAnonymous]
public ActionResult LoginPost(LoginViewModel model, string returnUrl, bool Relogin = false)
{
returnUrl = string.IsNullOrEmpty(returnUrl) || string.IsNullOrWhiteSpace(returnUrl) ? "/" : returnUrl;
if (string.IsNullOrEmpty(model.UserName))
return this.EmptyField(Resource_General.UserName);
if (string.IsNullOrEmpty(model.Password))
return this.EmptyField(Resource_General.Password);
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = SignInManager.PasswordSignIn(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
var user = db.Users.FirstOrDefault(x => x.UserName == model.UserName);
if (!user.IsActive)
{
AuthenticationManager.SignOut();
this.ShowMessage(MessageType.Error, Messages.LockedOutUser);
return Content("ERROR");
}
if (Url.IsLocalUrl(returnUrl))
return Content(returnUrl);
else
return Content("/Home");
case SignInStatus.LockedOut:
this.ShowMessage(MessageType.Error, Messages.LockedOutUser);
return Content("ERROR");
case SignInStatus.RequiresVerification:
case SignInStatus.Failure:
default:
this.ShowMessage(MessageType.Error, Messages.WrongPassword);
return Content("ERROR");
}
}
Ajax Form
#using (Ajax.BeginForm("LoginPost", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, new AjaxOptions { OnSuccess = "OnSuccess" }, new { #id = "login-form" }))
{
#Html.AntiForgeryToken()
<div class="network-login-fields">
<div class="form-group">
<div class="input-group col-xs-12">
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control", placeholder = Resource_General.UserNamePlaceHolder, name = "loginname", autofocus = "true" })
</div>
</div>
<div class="form-group">
<div class="input-group col-xs-12">
#Html.PasswordFor(m => m.Password, new { #class = "form-control", placeholder = Resource_General.PasswordPlaceHolder, name = "password" })
</div>
</div>
<div class="network-login-links">
<button class="btn btn-default"><i class="fa fa-sign-in"></i> #Resource_General.Login</button>
</div>
</div>
}
Javascript
function OnSuccess(data) {
if (data != "ERROR") {
window.location.href = data;
}
}
Here in the javascript, you need to handle the ajax form OnSuccess and do something if the response is "OK" or "ERROR".
In your main javascript file you need to include this:
Handle Messages
// START Messages and Notifications
function handleAjaxMessages() {
$(document).ajaxStart(function () {
Openloading();
}).ajaxComplete(function (e, xhr, settings) {
CloseLoading();
}).ajaxSuccess(function (event, request) {
checkAndHandleMessageFromHeader(request);
}).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
if (thrownError !== "abort") {
CloseLoading();
NotifyError();
}
OnInit();
});
}
function checkAndHandleMessageFromHeader(request) {
var msg = request.getResponseHeader('X-Message');
if (msg) {
var title = NotifyHeader(request.getResponseHeader('X-Message-Type'));
Notify(msg, title, request.getResponseHeader('X-Message-Type'));
}
}
function NotifyHeader(type) {
console.log(type);
var title = "";
if (type == "error")
title = CustomScriptsLocales.ErrorTitle;
if (type == "success")
title = CustomScriptsLocales.SuccessTitle;
if (type == "warning")
title = CustomScriptsLocales.WarningTitle;
if (type == "info")
title = CustomScriptsLocales.InfoTitle;
console.log(title);
return title;
}
function Notify(message, title, type) {
if (title == null || title == "" || title == undefined) {
title = NotifyHeader(type);
}
PNotify.desktop.permission();
var notice = new PNotify({
title: title,
text: decodeHtml(message),
nonblock: {
nonblock: true,
nonblock_opacity: .55
},
buttons: {
closer: true,
},
desktop: {
desktop: false,
},
hide: true,
type: type,
delay: 2000,
insert_brs: true,
remove: true,
});
}
function NotifyError() {
Notify(CustomScriptsLocales.ErrorMessage, CustomScriptsLocales.ErrorTitle, "error");
}
// END Messages and Notifications
And call it inside a ready function:
$(document).ready(function () {
handleAjaxMessages();
}
Note: I use the PNotify plugin to show notifications. If you don't want notifications just exclude all this javascript "Handle Messages".

Controller return incorrect data with ajax ActionLink in mvc

several days ago with searching i put an ajax button inside my page, but i didn't know the issue till now, the thing is happen, is that the result i receive is not the result from ajax redirection, but is result from first processing (though i was wonder why it do it twist)...
And what i wanna do is perform filtering through link button instead of button.
so i have two action, one is for my ajax button, and second for my index:
1.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ChooseCategoryAction(int? id)
{
Monitor.Enter(monitorObj);
// Save code here...
Session.Add("FilterCategory", id);
return RedirectToAction("Index");
}
2.
public override ActionResult Index()
{
.
.
.
int? id = (Session["FilterCategory"] != null) ? int.Parse(Session["FilterCategory"].ToString()) : (int?)null;
List<LinkEntity> filterList = null;
int catId = id ?? -1;
if (catId != -1)
{
filterList = new List<LinkEntity>();
foreach (LinkEntity linkEntity in linkList.Where(
where =>
(catId == 0 && #where.Category == null) ||
(#where.Category != null && #where.Category.Id == catId)).Select(
select =>
new LinkEntity(#select.Id, #select.Name, #select.Link, #select.Description,
#select.Category)))
{
filterList.Add(linkEntity);
}
}
else
{
filterList = linkList;
}
return View(filterList);
}
My View is like this:
<div class="split-left">
#if (ViewBag.CategoriesTags != null)
{
foreach (var cat in ViewBag.CategoriesTags)
{
<div class="link-item-category">
#using (Html.BeginForm())
{
#Ajax.ActionLink((string)cat.Name, "ChooseCategoryAction","Home", new { id = cat.Id }, new AjaxOptions { HttpMethod = "POST" }, new{#class = "category-link"})
}
</div>
}
}
</div>
When i click the link it should goes to Ajax method, then inbox, filter my data and return a view, but it first goes to inbox, then to Ajax, again to inbox, next it goes value seem to be true, but result which return is incorrect
i also before reaching to filtering step, tried following:
#Html.Hidden(((int)cat.Id).ToString())
#Html.ActionLink((string)cat.Name, "ChooseCategoryAction", "Home", null, new { #class = "category-link", onclick = "return false;" })
with following script:
<script type="text/javascript">
$(document).ready(function () {
$('.category-link').click(function () {
$(this).closest('form')[0].submit();
});
});
</script>
But it don't return to controller or don't refresh page

eval for parsing JSON giving undefined

I am working on Grails framework. I have 2 domain classes Country and City with one-to-many relationship. My idea is when the page is loaded the gsp will have two select boxes, one populating the countries and when any country selected the cities of that country are populated in second select box. here i am using grails ajax (jquery).
import grails.converters.JSON
class CountryController {
def index() { redirect action: 'getCountries' }
def getCountries() {
def countries = Country.list()
render view:'list', model:[countries:countries]
}
def getCities() {
def country = Country.get(params.id)
render country?.city as JSON
}
}
When getCities action is fired i am getting the JSON as below:
[
{
"class":"com.samples.City",
"id":3,
"country":{
"class":"Country",
"id":2
},
"description":"California",
"name":"California"
},
{
"class":"com.samples.City",
"id":4,
"country":{
"class":"Country",
"id":2
},
"description":"Dalls",
"name":"Dalls"
}
]
But from my gsp page when evaluating JSON with eval function, its returning "undefined".
<g:select name="countrySelect" from="${countries}"
optionKey="id" optionValue="name"
noSelection="[null:'Select Country']"
onchange="${
remoteFunction(action: 'getCities',
update: message,
params: '\'id=\' + this.value',
onSuccess:'updateCity(data)')
}"/>
<br/>
City :: <g:select name="city" id="city" from=""></g:select>
Following code in tag
<head>
<g:javascript library="jquery"></g:javascript>
<g:javascript>
function updateCity(data) {
alert('done');
var cities = eval("(" + data.responseText + ")") // evaluate JSON
alert(cities)
var rselect = document.getElementById('city')
// Clear all previous options
var l = rselect.length
while (l > 0) {
l--
rselect.remove(l)
}
//build cities
for(var i=0; i < cities.length; i++) {
var opt = document.createElement('option');
opt.text = cities[i].name
opt.value = cities[i].id
try{
rselect.add(opt,null) //For Non IE
}catch(ex){
rselect.add(opt) //For IE
}
}
}
</g:javascript>
<r:layoutResources />
</head>
Can anyone help me finding out where is the problem?
I got it solved by using JQuery each method on JSON data.
<g:javascript>
function updateCity(data) {
var rselect = document.getElementById('city')
$.each(data, function(index, element) {
//alert(element.name);
var opt = document.createElement('option');
if(element.name !== undefined){
opt.text = element.name
opt.value = element.id
try{
rselect.add(opt,null) //For Non IE
}catch(ex){
rselect.add(opt) //For IE
}
}
});
}
</g:javascript>

Upload files with Jquery File Upload in ASP.NET MVC 3

Does anyone has a clean suggestion of instantiate this jquery's useful library.
I need to submit files and manage the Json response from the server.
I always get none json response within the Js code. I have reviewed some articles mentioning it but the code doesn't fit to the purpose.
The situation is: I achieve the submition and saving in the database but the Json response never arrives.
Thanks in advance.
This is my view code:
<script type="text/javascript">
$("#formUplImg").fileupload({
dataType: "json",
url:'#Url.Action("CreateJson","ProductImage")',
done: function (e, data) {
alert(data.StatusMessage);
}
});
</script>
#using (Html.BeginForm("CreateJson", "ProductImage", FormMethod.Post, new { id = "formUplImg", enctype = "multipart/form-data", #class = "jqtransform" }))
{
#Html.ValidationSummary(true)
<div class="rowElem">
<input type="file" id="Content" name="Content" />
</div>
<div class="rowElem">
#Html.ValidationMessageFor(item => item.Content)
</div>
<div class="rowElem">#Html.JQueryUI().Button("Guardar imagen", ButtonElement.Button, ButtonType.Submit, new { id = "guardar_imagen" })</div>
}
This is my controller action code:
[HttpPost]
public ContentResult CreateJson(UploadedFileInfo fileInfo)
{
try
{
if (fileInfo.Content == null)
throw new Exception("Hubo problemas con el envío. Seleccione un archivo a subir");
var file = new TempDocument
{
CreatedBy = User.Identity.Name,
CreationTime = DateTime.Now,
FileName = fileInfo.Content.FileName,
MimeType = fileInfo.Content.ContentType,
Size = fileInfo.Content.ContentLength,
Content = new byte[fileInfo.Content.ContentLength]//Image content to save
};
fileInfo.Content.InputStream.Read(file.Content, 0, fileInfo.Content.ContentLength);//Reading image content into ProductImage object
DocumentsManager.StorePendingDocuments.Add(file);
DocumentsManager.SaveTempDocuments();//Store each document uploaded to: TempDocument Table
TempData["SuccessMsg"] = "The image was saved successfully";
var json = new JavaScriptSerializer().Serialize(new { Success = true, StatusMessage = "El objeto fue insertado correctamente" });
return Content(json, "application/json");
}
catch (Exception exception)
{
TempData["ErrorMsg"] = exception.Message;
var json = new JavaScriptSerializer().Serialize(new { Success = false, StatusMessage = exception.Message });
return Content(json, "application/json");
}
}
Use return type of Action as ActionResult and use:
`return Json(new { Result = "Success" });`
So that on success you will get Json object containing result value.

Ajax get returns empty data

The data variable returns nothing when it should return "OK" or "EXISTS".
I have a template with an overlay effect. The income.html template has a form and a button "Add a new category", when you click on it a new window is displayed(overlay effect) with a tiny form.
income.html:
(document).ready(function(){
$("#new_cat").live("click", ( function() {
var cat_name = $("#nc").val();
if (cat_name) {
$.get("/cashflow/new_cat/0/", { name: cat_name, account: {{ account }} },
function(data){
if (data == "OK") {
$("#id_category").val(cat_name);
}
if (data == "EXISTS") {
var error = "The category already exists";
alert(error);
}
});
}
else {
var error = "Please enter a name";
alert(error);
}
}))
});
</script>
...
<form>{% csrf_token %}
<label for="name">Name:</label><input type="text" id="nc" />
<input type="submit" value="Submit" id="new_cat" />
</form>
views.py:
#login_required
def income(request, account_name):
account = account_name
if request.method == 'POST':
form = TransForm(user=request.user, data=request.POST)
if form.is_valid():
income = form.save(commit=False)
income.type = 0
income.account = Account.objects.get(
name = account_name,
user = request.user)
income.name = form.cleaned_data['name']
income.category = form.cleaned_data['category']
income.save()
uri = ("/cashflow/account/%s") % str(account_name)
return HttpResponseRedirect(uri)
else:
form = TransForm(user=request.user)
context = {
'TransForm': form,
'type': '0',
'account': account,
}
return render_to_response(
'cashflow/income.html',
context,
context_instance = RequestContext(request),
)
def new_cat(request, type):
if request.method == u'GET':
GET = request.GET
if GET.has_key(u'name'):
name = request.GET[u'name']
account = request.GET[u'account']
c = Category.objects.filter(name=name, account=account)
if c:
s = "EXISTS"
else:
c = Category(name = name, user = request.user,
type = type, account = account)
c.save()
s = "OK"
return HttpResponse(s)
Are you crossing domains? You cannot do cross-domain ajax requests. That includes subdomains.

Resources