ModelState.AddModelError alternative - asp.net-mvc-3

I am using ModelState.AddModelError to display error message to user when Model do not pass validation. What is the best method do display information message when validation is passed. I do not want to add additional HTML elements. Can I use ModelState object to send information messages?

You could test if the model is valid and display a corresponding message
#if (ViewData.ModelState.IsValid)
{
<div>Your model is valid</div>
}
Obviously if you don't want this to be displayed all the time even when you first arrive at the page you could use an additional view model boolean property to indicate whether you want to display the message or not. Then inside your POST action set its value to true when everything passes validation and in the view:
#if (Model.ShouldShowSuccess && ViewData.ModelState.IsValid)
{
<div>Your model is valid</div>
}

I built a PartialView to display success posts.
It's near the Html.ValidationSummary().
When a ModelState is valid I value a TempData variable with the IsValid message, so in my View I have this:
#Html.ValidationSummary()
#if (ViewData.ModelState.IsValid && TempData["ModelIsValidMsg"] != null)
{
#Html.Partial("PostSuccess", TempData["ModelIsValidMsg"])
}
In my Controller:
if (ModelState.IsValid)
{
TempData["ModelIsValidMsg"] = "Your success msg";
}
else
{
ModelState.AddModelError("Your error msg");
}
Inside the PartialView I display the TempData message.

Related

Return a warning (not an error) via Ajax remote validation

I have an MVC Ajax callback that checks to see if a user input is valid. This callback is invoked via the [Remote] attribute on the associated model property.
I've changed my design, and I've decided that I would really like to warn the user if the value is incorrect, but I don't want the incorrect value to prevent model validation.
A quick search turns up several threads describing very involved solutions to the general problem of wiring up "unobtrusive warnings" similar to the "unobtrusive validation" magic baked into MVC (for example this SO post). I'm not looking for a general solution, and I don't want to spend a lot of time and energy on this, but I'm wondering if some Ajax guru knows of something I can return from the Ajax server routine that would have the effect of causing the unobtrusive validation client-side code to put up the message without triggering the validation error.
FYI, my existing server-side code looks like this:
public async Task<ActionResult> CouponCodeExists(string couponCode, int? planId)
{
if (some_logic) {
return Json("Coupon code is already taken", JsonRequestBehavior.AllowGet);
} else {
return Json(true, JsonRequestBehavior.AllowGet);
}
}
A RemoteAttribute is a validation attribute and triggering it will add a validation error to jQuery.validate.js and prevent the form from submitting. If you just want a warning message, and still allow the form to submit, you can just make your own ajax call in the inputs .change() event.
Assuming you have #Html.TextBoxFor(m => m.couponCode) in the view, add a placeholder for the message - say <div id="couponwarning">Coupon code is already taken</div> and style in as display: none;. Then add the following scripts
var url = '#Url.Action("CouponCodeExists")';
var warning = $('#couponwarning');
$('#couponCode').change(function() {
var code = $(this).val();
var id = .... // the value of your planId input?
$.get(url, { couponCode: code, planId: id }, function(response) {
if (response) {
warning.show();
}
});
});
$('#couponCode').keyup(function() {
warning.hide();
});
and the method can just return true to display the message, or null
if (some_logic) {
return Json(true, JsonRequestBehavior.AllowGet);
} else {
return Json(null, JsonRequestBehavior.AllowGet);
}

how to use custom validation message for html form in liferay6 with custom portlet?

I am using liferay to develop a custom portlet (mvc portlet) my problem is that i have one form in jsp page in HTML and and what i want is to validate some field of the forms.and on submit button its redirecting to another page.the validation i have done is working but what happen is when am clicking the submit button its redirect to another page and on that page its just showing default error from liferay. What i want is to display same page if request not completed with the error message near the field which validation has false.
How can i solve this issue?
this is my code to checking validation while add method in action class
public void addRestaurant(ActionRequest request, ActionResponse response) {
log.info("Inside addRegistration");
List<String> errors = new ArrayList<String>();
restaurant rest = RestaurantActionUtil
.getRestaurantFromRequest(request);
boolean restValid = RestaurantValidator
.validateRestaurant(rest, errors);
if (restValid) {
try {
log.info(rest);
restaurant test = restaurantLocalServiceUtil
.addrestaurant(rest);
if (test == null) {
log.error("Restaurant was Found Null");
response.setRenderParameter("jspPage", errorJSP);
return;
}
} catch (SystemException e) {
log.error(e);
/*
* If there is an error then divert the control to the error
* page.
*/
response.setRenderParameter("jspPage", errorJSP);
return;
}
SessionMessages.add(request, "restaurant-added");
return;
} else {
for (String error : errors) {
SessionErrors.add(request, error);
}
SessionErrors.add(request, "error-while-adding");
request.setAttribute("rest", rest);
return;
}
}
This is my validator class
public class RestaurantValidator {
public static boolean validateRestaurant(restaurant rest, List errors) {
boolean valid=true ;
if (Validator.isNull(rest.getName())) {
errors.add("Name-required");
valid = false;
}
if (Validator.isNull(rest.getLicensekey())) {
errors.add("license-key-required");
valid = false;
}
following is my view.jsp code
Restaurant Name*
" />
<span class="help-block">help block</span>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<label>License Key<span class="f_req">*</span></label>
<liferay-ui:error key="license-key-required" message="license-key-required" />
<input type="text" name="licensekey" class="span8" value="<%=restaurantOBJ.getLicensekey() %>"/>
</div>
</div>
the error message is deisplaying on the redirected page with following way rather then on same page i want the error near textbox of name with the error of "Name_required"
The error message is displaying on the redirected page the following way rather then on same page, I want the error near the name-textbox with the error of "Name_required".
what I want is when name is blank then it should not submit the form and give error near text box of name in my view.jsp page.
I would try to answer your question, try to set a actionResponse.setRenderParameter("valid", "NO"); in your addRestaurant method if the validation fails.
And get this parameter in the doView method and set the renderPage accordingly in this method: include(renderPage, renderRequest, renderResponse); at the end of the doView method.
If you can provide all the information in your question with nice formatting like the validator method, <aui:form> and the javascript method called on onSubmit then we can go ahead with looking for other solution.
In the mean-while you can try this out and see if it works. :-)

ValidationSummary for server side errors is not working

Client side Validation and ValidationSummary is working fine for my project (MVC4 + Razor + Unobtrusive JS) but the Server side errors are not shown on my view and if there was any client side error, it does not get removed from the view (it does from the ModelState). I have tried on both Chrome14 and IE9
Server side errors are being added to the model as ModelState.AddModelError(string.Empty, ModelState.AllErrors()); and shown to the view as #Html.ValidationSummary(false).
Edit
Simple form submit is working fine, it shows multiple error messages returned from the server and updates error messages, but, ajax based form submit is not working error messages returned by ajax based form submit are not shown at all.
Here is a sample demonstration of how the request is being made
#*... View contents related to Master Model ...*#
#using (Ajax.BeginForm("ActionToAddRecord", new AjaxOptions()))
{
#Html.Action("ActionToAddRecord")
<input type="submit" value="Add Record"/>
}
#*... View contents related to Master Model ...*#
ActionToAddRecord is a partial view representing a model contained by a master model
Errors are returned as
[HttpGet]
public ActionResult ActionToAddRecord()
{
return View();
}
[HttpPost]
public ActionResult ActionToAddRecord(childModel model)
{
ModelState.AddModelError(string.Empty, "First error message");
ModelState.AddModelError(string.Empty, "Second error message");
return View(model);
}
Edit
I saw a similar functionality in templated MVC application by VS2010, the dialog based log in form. Error messages are returned as Json and then JS is being used to display them, IMO, seems like MS made Ajax based requests quite easy and concise (Ajax.BeginForm) but missing the error handling part. Right now i am not willing to use JS for this, there might be a better way to get this type of error handling dealt automatically.
Solved, with a small error.
Master View
#*Master View Contents*#
#using (Ajax.BeginForm("AddPaymentCurrency", new AjaxOptions { UpdateTargetId = "paymentCurrency" }))
{
<div id="paymentCurrency">
#{Html.RenderPartial("PaymentCurrency", Model.PaymentCurrencyNew);}
</div>
}
PaymentCurrency View
#*Model Editors*#
#Html.ValidationSummary(false)
<input type="submit" value="Add Payment Currency"/>
<div id="paymentCurrencyList" style="width:inherit; height:auto; overflow:auto;">
#Html.Action("PaymentCurrencyList")
</div>
Controller
[HttpPost]
public ActionResult AddPaymentCurrency(PaymentCurrency model)
{
if (!ModelState.IsValid)
{
ModelState.AddModelError(string.Empty, ModelState.AllErrors());
return View("PaymentCurrency", model);
}
//Add login
return View("PaymentCurrency", model);
}
public ActionResult PaymentCurrencyList()
{
//var list = getList
return View(list);
}
small error
ValidationSummary is shown with fields highlighted and asterisk shown against them while adding invalid payment currency. Once a valid currency is added then ValidationSummary and asterisk is no more shown on invalid payment currency, just fields are highlighted.
Please help me to get it fixed, i would prefer not to change the current structure, otherwise i will start getting big error

Refreshing parent view when a partial view's form is submitted

I'm looking into using partial views in MVC3 using Razor, and I get my partial view to render and it works fine.
What I'd like to do, though, is refresh the parent view when the partial view is submitted.
Code in my parent view to render partial view
<div id="mydiv">
#{ Html.RenderAction("Add", "Request"); }
</div>
Action for parent view is simple,
public ActionResult Index()
{
List<obj> reqs = //some query
return View(reqs);
}
In my partial view's get action I have:
public ActionResult Add()
{
AddRequestViewModel vm = new AddRequestViewModel();
//set some stuff on the VM here
return PartialView(vm);
}
In the post action called by the partial view, if modelstate isn't valid, return PartialView(vm)
If it is valid, I'd like the parent and partial views to refresh.
I tried RedirectToAction, but this can't be called in an action called by a partial, apparently, and I tried return Index();, but this causes an issue with the code used to render the partial view,
Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Collections.Generic.List'1[DatRequests.Models.ReqRequest]', but this dictionary requires a model item of type 'DatRequests.ViewModels.AddRequestViewModel'.
Any suggestions on how to do this would be appreciated. The purpose of the page is to show a list of elements, and the partial contains a form to add a new element to the list.
Edit: The partial's model is different, as it contains data for selection, which is from a db, which is why I tried RenderAction, but I'm not sure if there are other ways of doing this.
When the partial view is submitted normally you submit it to some controller action. You could either submit it using a normal request or an AJAX request. If you use a normal request you could perform a standard redirect to the Index inside the POST controller action that will handle the form submission. If you use AJAX, you could return a JSON result pointing to the url that you want to redirect:
[HttpPost]
public ActionResult Foo(MyViewModel model)
{
if (!ModelState.IsValid)
{
return PartialView(model);
}
return Json(new { url = Url.Action("Index") });
}
and inside your AJAX success callback:
success: function(result) {
if (result.url) {
// we have a success
window.location.href = result.url;
} else {
// invalid modelstate => refresh the partial
$('#mydiv').html(result);
}
}
Probably RenderAction should not be used this way.
When using Html.RenderAction, a new/seperate request would be sent to the server. And you got another chance to load some data from db or somewhere else to display to the client. Also, you could apply OutputCache to this action. this is usually the way doing global cache.
Here you are doing a POST to the server. Either directly put a element here or using a partial view to do the Post. And in the corresponding action, do a RedirectToAction.
Do it with ajax or not isn't the point. my opinion is more about the right way using RenderAction

server side validation in the main view cause also validation in partial view, how to stop that?

I have layout with login partial view (username, password and submit button) and models ( some controls and submit button)with validation(server side and client side) displayed in normal views (#RenderBody() in layout).
My problem is when do server side validation in any of my views it also validate the login partial view because it execute the httppost function of the login. how can I stop that??
login view controller
[HttpGet]
public ActionResult LogOn()
{
return PartialView();
}
//
// POST: /Account/LogOn
[HttpPut]
public ActionResult LogOn(LogOnModel model)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
ViewBag.UserName = model.UserName;
}
else
{
ModelState.AddModelError("", Resources.Account.Account.LoginFailureText);
}
}
return PartialView(model);
}
and model controller
public ActionResult MyModel()
{
ViewBag.DisplayThxMsg = false;
return View();
}
[HttpPost]
public ActionResult MyModel(Models.FeedbacksModel feedback)
{
if (ModelState.IsValid)
{
//do something
}
else{
//do another thing
}
return View(feedback);
}
I find your question very difficult to understand. Im guessing your problem is you have a login partial control displayed as part of site layout and is shown on all pages. So while submitting any page, the username password validation kicks in, and you want to prevent that.
Understand that all validation # server - side happens while model binding, As properties are bound to the posted fields, the attributes on the fields are looked at and honored / catered to. So to prevent server side validation simply put the login partial view in it's own form so it is not sent while submitting other forms on the page.
In short have 2 forms - one form for login and one for feedback. Don't put all input fields in the same form.
If you still have validation errors after that, then it is because of other reasons like, type conversion problems. The default model binder will add some errors for basic type conversion issues (for example, passing a non-number for something which is an "int").The sample DataAnnotations model binder will fill model state with validation errors taken from the DataAnnotations attributes on your model.
EDIT
If you look at line number 125
#using (Html.BeginForm()){Html.RenderAction("LogOn", "Account");}
You have the above code which will render the login form.
It will do so inside the other form at line 45
<form id="form1" runat="server" method="post">
This has no end tag therefore it will encompass the whole document till </html>
You should change the structure from
<form id="form1" runat="server" method="post">
#using (Html.BeginForm()){Html.RenderAction("LogOn", "Account");}
</form
to
<form id="form1" runat="server" method="post">
</form>
#using (Html.BeginForm()){Html.RenderAction("LogOn", "Account");}
This line #using (Html.BeginForm()){Html.RenderAction("LogOn", "Account");} will render this form <form id="LoginView1" action="LogOn"> and all child elements of it.
LATEST EDIT
In your layout page use this :
#Html.Partial("~/Views/Shared/LogOnPartial.cshtml", new LogOnModel())
instead of this :
#Html.Action("LogOnPartial", "Account")
The reason why it all works is, the LogOnPartial method marked with [HttpPost] is called because the request was in a POST context. What you want is, You just need the view without the action executing even when POSTing. The above code does that. It renders the view without calling the action method. MVC3 is sort of a stupid servent : It only knows that it should call the Action method marked with [HttpPost] when the request is in a post context. It doesn't know that the request is in a post context for another action (index) and not this one (logonpartial). So now you can remove this method
public ActionResult LogOnPartial()
{
return PartialView();
}
which will no longer be used.
Note that you need to change the account controller's LogOnPartial Method to return
return RedirectToAction("Index","Home"); instead of return PartialView(model); on successful login. And on FAILURE you cannot render a partialview as you have coded. You must return an entirely new View. It must neither be index nor LogonPartails - just return return View("Login_Error_View"); which has its own layout. Otherwise it will be difficult to control the workflow.

Resources