I want to do cusotm validation and return false and show message in case of validation fail.
In controller below code is used to submit posted data to database.
[HttpPost]
public JsonResult SubmitDa(IList<AdViewModel> s, String section)
{
...........
..........
ModelState.AddModelError("MessageError", "Please enter AttendanceDate");
JSONSubmit r = new JSONSubmit();
r.ErrorCount = iError;
r.errors = errors;
return Json(r, JsonRequestBehavior.AllowGet);
}
Below is the code in view file (cshtml)
#Html.ValidationMessage("MessageError")
.....
$.AJAX call to `SubmitDa` controller's method.
Message is not appearing at "MessageError" validation message. please suggest me what is wrong here.
Thanks
If you want to use the modelstate for errors you shouldn't really be sending a JSON response. Having said that you can handle it by having the controller return JSON only in the case of success, and the page handles the response differently
IE:
[HttpPost]
public ActionResult SubmitDa(IList<AdViewModel> s, String section)
{
...........
..........
ModelState.AddModelError("MessageError", "Please enter AttendanceDate");
JSONSubmit r = new JSONSubmit();
r.ErrorCount = iError;
r.errors = errors;
if (r.ErrorCount != 0)
return Json(r, JsonRequestBehavior.AllowGet);
return View("ViewName", s); // <-- just return the model again to the view,
// complete with modelstate!
}
on the page something like:
<script>
$("#buttonId").click({
$.ajax({
type: "POST",
url: "PostBackURL",
data: $("#formID").serialize(),
success: function (response){
//test for a property in the JSON response
if(response.ErrorCount && response.ErrorCount == 0)
{
//success! do whatever else you want with the response
} else {
//fail - replace the HTML with the returned response HTML.
var newDoc = document.open("text/html", "replace");
newDoc.write(response);
newDoc.close();
}
}
});
});
</script>
Related
I have a requirement that when a user successfully posts some form data, I would like a modal dialog to display whether the POST was successful or not, along with resetting the view to it's empty state (if successful).
How would I go about this?
I have the POST logic working correctly, but as it stands, there is no feedback indicating that the operation was a success or not.
Answer 1:
public ActionResult Index(string message)
{
if(!string.IsNullOrEmpty(message)){
ViewData["successmessage"]=message; //Or you can use Viewbag
}
return View();
}
[HttpPost]
public ActionResult Index()
{
...............
return RedirectToAction("Index",new{ message="Saved successfully" });
}
Just alert ViewData["successmessage"] on View with Javascript alert box.
On View just show alert box as alert('#ViewData["successmessage"]')
Answer 2:
[HttpPost]
public ActionResult Index()
{
...............
TempData["successmessage"] = "Saved successfully";
return RedirectToAction("Index");
}
View(Index.cshtml) :-
#{
var message = TempData["successmessage"] ?? string.Empty;
}
<script type="text/javascript">
var message = '#message';
if(message)
alert(message);
</script>
Firstly, you have to add a listener at the front side, mostly with jquery.ajaxSetup function.
Then you need to let front listener know it is the successful request to display dialog, add a special code or something like that.
C# Code:
return Json(new{Code = 200, Message = "some text"}, JsonRequestBehavior.AllowGet);
Javascript Code:
$.ajaxSetup({
success: function(xhr){
var response = JSON.parse(xhr.responseText);
if(response & response.Code == 200 && response.Message) {
// pop up dialog with message here
}
}
})
I have a view (Index.cshtml) with a grid (Infragistics JQuery grid) with an imagelink. If a user clicks on this link the following jquery function will be called:
function ConfirmSettingEnddateRemarkToYesterday(remarkID) {
//Some code...
//Call to action.
$.post("Home/SetEnddateRemarkToYesterday", { remarkID: remarkID }, function (result) {
//alert('Succes: ' + remarkID);
//window.location.reload();
//$('#remarksgrid').html(result);
});
}
Commented out you can see an alert for myself and 2 attempts to refresh the view. The location.reload() works, but is basically too much work for the browser. The .html(result) posts the entire index.cshtml + Layout.cshtml double in the remarksgrid div. So that is not correct.
This is the action it calls (SetEnddateRemarkToYesterday):
public ActionResult SetEnddateRemarkToYesterday(int remarkID) {
//Some logic to persist the change to DB.
return RedirectToAction("Index");
}
This is the action it redirects to:
[HttpGet]
public ActionResult Index() {
//Some code to retrieve updated remarks.
//Remarks is pseudo for List<Of Remark>
return View(Remarks);
}
If I don't do window.location.reload after the succesfull AJAX post the view will never reload. I'm new to MVC, but i'm sure there's a better way to do this. I'm not understanding something fundamental here. Perhaps a nudge in the right direction? Thank you in advance.
As you requesting AJAX call, you should redirect using its response
Modify your controller to return JSONResult with landing url:
public ActionResult SetEnddateRemarkToYesterday(int remarkID) {
//Some logic to persist the change to DB.
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index", "Controller");
return Json(new { Url = redirectUrl });
}
JS Call:
$.post("Home/SetEnddateRemarkToYesterday", { remarkID: remarkID }, function (result) {
window.location.href = result.Url
});
After Ajax post you need to call to specific Url..
like this..
window.location.href = Url
When using jQuery.post the new page is returned via the .done method
jQuery
jQuery.post("Controller/Action", { d1: "test", d2: "test" })
.done(function (data) {
jQuery('#reload').html(data);
});
HTML
<body id="reload">
For me this works. First, I created id="reload" in my form and then using the solution provided by Colin and using Ajax sent data to controller and refreshed my form.
That looks my controller:
[Authorize(Roles = "User")]
[HttpGet]
public IActionResult Action()
{
var model = _service.Get()...;
return View(model);
}
[Authorize(Roles = "User")]
[HttpPost]
public IActionResult Action(object someData)
{
var model = _service.Get()...;
return View(model);
}
View:
<form id="reload" asp-action="Action" asp-controller="Controller" method="post">
.
.
.
</form>
Javascript function and inside this function I added this block:
$.ajax({
url: "/Controller/Action",
type: 'POST',
data: {
__RequestVerificationToken: token, // if you are using identity User
someData: someData
},
success: function (data) {
console.log("Success")
console.log(data);
var parser = new DOMParser();
var htmlDoc = parser.parseFromString(data, 'text/html'); // parse result (type string format HTML)
console.log(htmlDoc);
var form = htmlDoc.getElementById('reload'); // get my form to refresh
console.log(form);
jQuery('#reload').html(form); // refresh form
},
error: function (error) {
console.log("error is " + error);
}
});
How to use $.post or $.getJSON to get json from mvc controlller but not working below? Would you like help me?
var controlRole = function () {
var _url = 'IsStudent/';
console.log('IsStudent');
$.post(_url, {}, function (data) {
console.log('IsStudent2');
if (data == "true") {
$('#btnSent_').hide();
$('#btnDraft_').hide();
$('#btn_Inbox_').show();
$('#btnTrash_').show();
$.post('FillProgramListByUser/', {}, function (result) {
console.log('IsStudent3');
console.log(result);
$("#liProgramContainer ul").append('<li ><a class="btn" href="javascript:;" data-title="Sent">'+result.Name+'</a><b></b></li>');
});
// $.getJSON("FillProgramListByUser/", user, updateFields);
}
else {
$('#btnSent_').show();
$('#btnDraft_').show();
$('#btn_Inbox_').show();
$('#btnTrash_').show();
}
});
}
Controller side:
public JsonResult FillProgramListByUser()
{
string UserName = SessionVariables.CurrentUser.UserName;
int OrganizationId = SessionVariables.CurrentUser.OrganizationId;
IList<Program> programs = new List<Program>();
if (UserName != "system_admin")
{
programs = Uow.Programs.GetAll().Where(q => q.OrganizationId == OrganizationId).ToList();
}
return Json(programs, "application/json", Encoding.UTF8, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public string IsStudent()
{
string UserName = SessionVariables.CurrentUser.UserName;
if (UserName != "system_admin")
{
return "true";
}
else
{
return "false";
}
}
Your controller action should return a JsonResult and not some strings:
[HttpPost]
public ActionResult IsStudent()
{
string UserName = SessionVariables.CurrentUser.UserName;
if (UserName != "system_admin")
{
return Json(new { success = true });
}
return Json(new { success = false });
}
Also in your FillProgramListByUser action you don't need to be explicitly setting the content type response header nor the encoding:
public ActionResult FillProgramListByUser()
{
string UserName = SessionVariables.CurrentUser.UserName;
int OrganizationId = SessionVariables.CurrentUser.OrganizationId;
IList<Program> programs = new List<Program>();
if (UserName != "system_admin")
{
programs = Uow.Programs.GetAll().Where(q => q.OrganizationId == OrganizationId).ToList();
}
return Json(programs, JsonRequestBehavior.AllowGet);
}
Also adapt your script so that the urls are not hardcoded as in your example but you used URL helpers to generate them:
<script type="text/javascript">
var controlRole = function () {
var isStudentUrl = '#Url.Action("IsStudent")';
$.post(isStudentUrl, function (data) {
if (data.success) {
$('#btnSent_').hide();
$('#btnDraft_').hide();
$('#btn_Inbox_').show();
$('#btnTrash_').show();
var fillProgramListByUserUrl = '#Url.Action("FillProgramListByUser")';
$.post(fillProgramListByUserUrl, function (result) {
$("#liProgramContainer ul").append('<li><a class="btn" href="javascript:;" data-title="Sent">'+result.Name+'</a><b></b></li>');
});
} else {
$('#btnSent_').show();
$('#btnDraft_').show();
$('#btn_Inbox_').show();
$('#btnTrash_').show();
}
});
};
</script>
Next put breakpoints in your controller actions and see if they are hit. Also don't forget to look at the network tab of your javascript debugging tool (FireBug or Chrome Developer Toolbar) which is where you will see the exact AJAX request being sent to the server and what does the server respond to. You will see the HTTP status code returned and you could also see the contents of the response. If the status code is non 2xx the success callback of your AJAX request will not be executed.
Another thing you should check is the Program model which is being returned by your FillProgramListByUser controller action. In there you are attempting to JSON serialize an IList<Program> but be careful: if this Program class has some circular references (often happens if you don't use view models but are directly passing your EF domain models to the views) you won't be able to JSON serialize it. The answer is of course obvious: use a view model.
Suppose you have the following controller action
[HttpPost]
public ActionResult Save( CustomerModel model )
{
if (!ModelState.IsValid) {
//Invalid - redisplay form with errors
return PartialView("Customer", model);
}
try {
//
// ...code to save the customer here...
//
return PartialView( "ActionCompleted" );
}
catch ( Exception ex ) {
ActionErrorModel aem = new ActionErrorModel() {
Message = ex.Message
};
return PartialView( "ActionError", aem );
}
}
And suppose you call this action using jQuery:
$.ajax({
type: "post",
dataType: "html",
url: "/Customer/Save",
sync: true,
data: $("#customerForm").serialize(),
success: function(response) {
/*
??????
*/
},
error: function(response) {
}
});
I would like to be able to distinguish between the results I am getting to handle them in different ways on the client. In other words how can I understand that the action
returned the same model because has not passed validation
returned one of the views that represents error info/messages
Any suggestion?
One way to handle this is to append a custom HTTP header to indicate in which case we are falling:
[HttpPost]
public ActionResult Save( CustomerModel model )
{
if (!ModelState.IsValid) {
//Invalid - redisplay form with errors
Response.AppendHeader("MyStatus", "case 1");
return PartialView("Customer", model);
}
try {
//
// ...code to save the customer here...
//
Response.AppendHeader("MyStatus", "case 2");
return PartialView( "ActionCompleted" );
}
catch ( Exception ex ) {
ActionErrorModel aem = new ActionErrorModel() {
Message = ex.Message
};
Response.AppendHeader("MyStatus", "case 3");
return PartialView( "ActionError", aem );
}
}
And on the client side test this header:
success: function (response, status, xml) {
var myStatus = xml.getResponseHeader('MyStatus');
// Now test the value of MyStatus to determine in which case we are
}
The benefit of this is that the custom HTTP header will always be set in the response no matter what content type you've returned. It will also work with JSON, XML, ...
Remark 1: To avoid cluttering you controller action with all those Response.AppendHeader instructions you could write a custom ActionResult allowing you to directly specify the value of this header so that you simply return this.MyPartialView("Customer", model, "case 1")
Remark 2: Remove this sync: true attribute from the request because it makes my eyes hurt (in fact I think you meant async: 'false').
You could check for an element unique to that view, for example:
$.ajax({
type: "post",
dataType: "html",
url: "/Customer/Save",
sync: true,
data: $("#customerForm").serialize(),
success: function(response) {
var resp = $(response);
if($(resp.find("#customer").length) {
//customer returned
} else if($(resp.find("#completed").length) {
//completed view
} else if($(resp.find("#error").length) {
//error view
}
},
error: function(response) {
}
});
I have the following code which is not working as expected. I want to have a retrun from the controller and using alert display the value returned from the controller.
$('#change').dialog({
autoOpen: false,
width: 380,
buttons: {
"Close": function() {
$(this).dialog("close");
},
"Accept": function() {
var test = $("#ChangePasswordForm").submit();
alert(test);
}
}
});
In my controller I want to return a string
[AcceptVerbs(HttpVerbs.Post)]
public string ChangePassword(string Name)
{
var msg = "Cool!";
if (name != null)
return msg;
}
How can I do that?
Your controller needs to return a type that derives from an ActionResult.
If you want to display a simple confirmation message you can add it to the ViewData bag like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ChangePassword(string name)
{
if (!string.IsNullOrEmpty(name))
{
ViewData["msg"] = "Cool";
}
return View();
}
Then, in your view, check for the presence of the value, and display it if it's there:
<% if(ViewData["msg"] != null) { %>
<script type="text/javascript">alert('<%= ViewData["msg"].ToString() %>')</script>
<%} %>
First of all, im assuming you are using an ajax form for this. I also assume you have a or something for putting your text into. All you have to do is set the UpdateTargetId to point at the id of the element you want to update with the text
<%using (Ajax.Form("ChangePasswordForm", new AjaxOptions { UpdateTargetId = "result" })) %>
.
[HttpPost]
public ContentResult ChangePassword(string s)
{
var msg = "Cool!";
if ( s != null ? return Content(msg, "text/plain") : return Content("An error has occured", "text/plain") );
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ChangePassword(string Name)
{
var msg = "Cool!";
if (name != null)
{
return Content(msg, "text/plain");
}
else
{
return Content("Error...", "text/plain");
}
}
Don't submit the form as that will perform a postback and cause the dialog to be removed.
Instead perform an AJAX post to the Controller Action and return a JsonResult containing the data.
Hook into the success callback from the Ajax request, and call alert passing the data from the Json object.
You'll probably wan't to use a loading mask after clicking submit so the user knows something is going on.