Implementing Validation in MVC - c#

Trying to validate my Phone Number so no one can input random letters inside the input box. I do have the unobtrusive and validate scripts. So far I have tried a few things inside my Model,
[RegularExpression(#"^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$", ErrorMessage = "Not a valid Phone number")]
[Display(Name = "Phone")]
public string SMSPhoneNumber;
or
[DataType(DataType.PhoneNumber)]
public string SMSPhoneNumber;
This is my View
<form role="form" action="#">
#Html.AntiForgeryToken()
<div class="form-group">
<label class="control-label"><b>Phone Number</b></label>
#Html.TextBoxFor(model => model.SMSPhoneNumber, new {#class = "form-control", #placeholder = "Enter Phone Number", #id = "phoneNumber", Name = "phoneNumber", data_val_required = "Please enter a phone number"})
#Html.ValidationMessageFor(model => model.SMSPhoneNumber, null, new { #class = "text-danger" })
</div>
<button type="button" data-dismiss="modal" class="btn dark btn-outline"> Cancel</button>
<button type="button" data-toggle="modal" id="" class="btn green" onclick="javascript: updateDatabase();">Submit</button>
</form>
This is my controller
[HttpPost]
public ActionResult UpdatePhoneNumber(string phoneNumber)
{
if (ModelState.IsValid)
{
return View();
}
}
The validation is still not working, what could be the issue?
Thanks

The reason your do not get client side validation is that you have changed the name attribute by using new { Name = "phoneNumber" } and you have not created a validation message placeholder for phoneNumber (just one for SMSPhoneNumber).
Under no circumstances should you ever change the name attribute. Nor should you be adding data-val-* attributes (and its not clear why your changing the id attribute). The HtmlHelper methods will always generate the correct html for model binding and validation when used correctly.
The reason you do not get any server side validation is that your not binding to your model, just to a string.
Change the view code to
#Html.TextBoxFor(m => m.SMSPhoneNumber, new { #class = "form-control", placeholder = "Enter Phone Number" })
#Html.ValidationMessageFor(m => m.SMSPhoneNumber, null, new { #class = "text-danger" })
and change the POST method to receive your model (assuming its say public class Company), then
[HttpPost]
public ActionResult UpdatePhoneNumber(Company model)

Related

Localization/Validation - MVC C# model only taking my default resource file instead of my other language selected

I am currently trying to get the validation from the backend models to the razor view using resource files. I have 2 languages setup, (en, fr) but even though French is selected, the error message is always in English.
I have tried multiple online tutorial / looking at other people having similar problem but none of the fixes worked for me.
my viewmodel example:
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(GlobalRes))]
[Display(Name = "Username", ResourceType = typeof(GlobalRes))]
public string Username { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(GlobalRes))]
[DataType(DataType.Password)]
[Display(Name = "Password", ResourceType = typeof(GlobalRes))]
public string Password { get; set; }
Razor view:
<div class="form-group">
#Html.LabelFor(m => m.Username, new { #class = "col-md-12" })
<div class="col-md-12">
#Html.TextBoxFor(m => m.Username, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Username, "", new { #class = "text-danger"})
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-12" })
<div class="col-md-12">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Password, "", new { #class = "text-danger" })
</div>
</div>
Inspecting the html in your browser after changing the language and submitting the form.
<input class="input-validation-error form-control" data-val="true" data-val-required="Ce champ est requis." id="Username" name="Username" type="text" value="">
<span class="field-validation-error text-danger" data-valmsg-for="Username" data-valmsg-replace="true">This field is required.</span>
<input class="input-validation-error form-control" data-val="true" data-val-required="Ce champ est requis." id="Password" name="Password" type="password">
<span class="field-validation-error text-danger" data-valmsg-for="Password" data-valmsg-replace="true">This field is required.</span>
What the expected results should be is, based on the language selected, the error message should be in french. If you inspect the input box, you can see the correct value being added in french. When submitting the form, you actually only get the english value instead of the expected one.
Thank you in advance!
I had this problem also but I find a simple way, I controller add this code.
if (ModelState.IsValid)
{
}
else
{
ModelState.Clear();
TryValidateModel(Model);
}
I was having the exactly same issue. For me putting the resource files in App_GlobalResources folder solved my problem!
If that folder does not exist already you can create it.
I am using localization on Asp.Net MVC application.

DateTime value is not sending back to controller

I cant seem to find the problem here. Really stuck and need help. Im using Html.BeginForm and inside i have editorFor - model.DOB. Used post method but somehow it doesnt send the property back to my controller. Do help. I have other string property fields which is sending fine to the controller. Only date property not sending. TQVM in advance.
---------Edit---------
Just found out that if i use Edge - i need to use dd/MM/yyyy format. Then it will saves fine. If i use MM/dd/yyyy, then it will give null on the controller.
On chrome
using dd/MM/yyyy - gives me 'The field must be a date' error
using MM/dd/yyyy - gives me null.
---------Edit---------
Model
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
[Display(Name = "Date of Birth")]
public DateTime? PersonDOB { get; set; }
View
#model Models.CorporationModel
using (Html.BeginForm("Edit", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<div class="form-group">
#Html.LabelFor(model => model.PersonDOB, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PersonDOB, new { htmlAttributes = new { #class = "form-control", placeholder = "Format: 06/31/1998" } })
#Html.ValidationMessageFor(model => model.PersonDOB, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" name="action:PersonalSave" />
<input type="submit" value="Reprocess" class="btn btn-default" onclick="return confirm('Are you sure?')" name="action:PersonalReprocess" />
</div>
</div>
</div>
}
Controller
[HttpPost]
[MultipleButton(Name = "action", Argument = "PersonalReprocess")]
public ActionResult PersonalReprocess(int id, CorporationModel corporationModel, HttpPostedFileBase postedResultFile, HttpPostedFileBase postedPersonalFile)
{
corporationModel.Verified = "Processing";
return UpdatePersonal(id, corporationModel, postedResultFile, postedPersonalFile);
}
If i remove the
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
Im getting the 'The field must be a date error'. If i switch between month and date manually, then it saves without problem. However, when it pulls from the db, it will start with dd/mm/yyyy and then clicking on save will gives out 'the field must be a date error' again, so need to switch it manually.

How to auto fill fields in a form using #Html.EditorFor in ASP.net MVC 5?

I'm using an autogenerated form from visual studio for asp.net mvc 5 that saves information to a database. It's the create view with the standard scaffolding etc from asp.net with entity framework.
I like the way the form looks, but I need one field (datecreated) to at least be auto filled, (but preferably autofilled and hidden). The problem is I don't understand the autogenerated code at all and my efforts to look it up have not been successful. Nor have my efforts to understand it. I'm still a beginner with html helpers, which I think these are.
Here is the form element I am working with. The part in the middle is the part I need to change to autofill (the date created field), I think the relevant part is changing the EditorFor. but I don't know:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>New Patient:</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
... //other form items removed for simplicity
<div class="form-group">
#Html.LabelFor(model => model.DateCreated,"Date Created", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DateCreated, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DateCreated, "", new { #class = "text-danger" })
</div>
</div>
... //more items left out for simplicity
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
}
And the auto generated controller for this part looks like this:
// GET: Subjects/Create
public ActionResult Create()
{
return View();
}
// POST: Subjects/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Name,DOB,Male,Female,Address,City,ZIP,PhoneHome,PhoneCell,Email,EmergencyContact,EmergencyContactPhone,EmergencyContactRelationship,ReferredBy,DateCreated,Allergy,AllergyDescription,HighBloodPressure,LowBloodPressure,HeartCondition,Diabetes,Anemia,HighCholesterol,Pacemaker,Epilepsy,Pregnant,Cancer,STD,Pain,PainDescription,Headache,HeadacheDescription,CommonCold,HighBloodPressureConcern,Stress,Depression,Sleep,Menstruation,Fertility,WeightControl,Other")] Subject subject)
{
if (ModelState.IsValid)
{
db.SubjectDatabase.Add(subject);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(subject);
}
If you dont know how I can autofill and or hide the form element datecreated, could you please point me to where I might learn to figure this out myself. I think I am reasonable at programming, I just don't understand html helpers well, or the bind function in the controller.
Remove this part from your View
<div class="form-group">
#Html.LabelFor(model => model.DateCreated,"Date Created", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DateCreated, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DateCreated, "", new { #class = "text-danger" })
</div>
</div>
And then, inside your Controller remove DateCreated from Bind attribute and assign DateCreated property:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Name,DOB,Male,Female,Address,City,ZIP,PhoneHome,PhoneCell,Email,EmergencyContact,EmergencyContactPhone,EmergencyContactRelationship,ReferredBy,Allergy,AllergyDescription,HighBloodPressure,LowBloodPressure,HeartCondition,Diabetes,Anemia,HighCholesterol,Pacemaker,Epilepsy,Pregnant,Cancer,STD,Pain,PainDescription,Headache,HeadacheDescription,CommonCold,HighBloodPressureConcern,Stress,Depression,Sleep,Menstruation,Fertility,WeightControl,Other")] Subject subject)
{
if (ModelState.IsValid)
{
subject.DateCreated = DateTime.Now; //if you want UTC time, use DateTime.UtcNow
db.SubjectDatabase.Add(subject);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(subject);
}
The #Value can also be used to prefill in spots by using #Html.EditorFor:
Example:
#Html.EditorFor(c => c.Propertyname, new { #Value = "5" })
There is more information to be found at:
Html.EditorFor Set Default Value

The value is invalid yet should it is a valid input value

I'm creating a webpage using MVC 5, Visual Studio, C#.
In my view I have a remark page which the user is allowed to make a remark in a text box and click "save" to save the remark in a database. However, it is saying that the value of the remark is invalid when it shouldn't be.
The error is
The value 'Testing Remark' is invalid
yet it should be valid
In my model, I have a class called Recall, which has a
public string Remark {get; set;}
In the view I have
#using (Html.BeginForm())
{
<div class="form-group">
#Html.LabelFor(model=>model.Remark, htmlAttributes: new {#class ="control-label col-md-2"})
<div class="col-md-10">
#Html.TextAreaFor(model => model.Remark, 5, 50, new { #class = "text-danger"})
#Html.validationMessageFor(model => model.Remark, "", new { #class = "text-danger"})
</div>
</div>
<div class="form-group">
<input type="submit" value="save" class="btn btn-default" />
</div>
}
In the controller
....
not putting the controller code here since it should have nothing to do with the error I'm getting.
You should use data type MultilineText if you are using a TextArea:
[DataType(DataType.MultilineText)]
public string Remark { get; set; }
Or just change the TextAreaFor to a TextBoxFor if you don't need multi line text:
#Html.TextBoxFor(model => model.Remark, new { #class = "text-danger"})

Override EditorFor ID and name

I'm building a blog website. I want users to be able to edit their posts.
I need to change the name of the HTML helper to match my model so I can use remote validation.
Model
[RegularExpression("[a-z]{1,50}", ErrorMessage = "URL String must be in lowercase")]
[Required(ErrorMessage = "Unique URL is required")]
[Remote("doesURLExist", "Post", HttpMethod = "POST",
ErrorMessage = "URL already exists. Please enter a different URL.")]
public string URLString { get; set; }
HTML, Using the viewbag to pass through my pre populated data.
<div class="form-group">
#Html.LabelFor(model => model.post.URLString, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.post.URLString, new { htmlAttributes = new { #Value = ViewBag.postURL, #class = "form-control", #name = "URLString" } })
#Html.ValidationMessageFor(model => model.post.URLString, "", new { #class = "text-danger" })
</div>
</div>
The prepopulated fields work great like this but my remote validation doesnt work. the name attribute needs to be "URLString" but it comes up as post.URLString which cant be used in my remote method.
Here is my remote method to check for existing URLStrings
[HttpPost]
public JsonResult doesURLExist(String URLString)
{
var allposts = _unitOfWork.PostRepository.Get();
if (allposts.Count(p => p.URLString == URLString) == 0)
{
return Json(true, JsonRequestBehavior.AllowGet);
}
return Json(false, JsonRequestBehavior.AllowGet);
}
I have gotten the remote validation to work using the raw HTML and manually changing the name attribute.
Here is the raw html that the helper outputs when I view source in google chrome. I copied it and changed the name.
<div class="form-group">
<label class="control-label col-md-2" for="post_URLString">URLString</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true"
data-val-regex="URL String must be in lowercase" data-val-regex-pattern="[a-z]{1,50}"
data-val-remote="URL already exists. Please enter a different URL." data-val-remote-additionalfields="" data-val-remote-type="POST" data-val-remote-url="/Post/doesURLExist"
data-val-required="Unique URL is required" id="post_URLString" name="URLString" type="text" value= />
<span class="field-validation-valid text-danger" data-valmsg-for="URLString" data-valmsg-replace="true"></span>
</div>
</div>
So that works great! The issue is I cant use my viewbag to prepopulate the data.
So I guess I have 2 problems lets just solve the easier one.
1. How do i get model data in the HTML Value field. value = Model.post.URLString doesnt work.
How do I override the HTML name attribute #name = "URLString"
I'm pretty new to c# I might be missing something really obvious here.
Got it. Because the name of my form element kept have a post. before the name I couldn't use the URLString.
I instead pass a post object through and get the URL String that way.
I also pass through the ID for a more thorough check.
[HttpPost]
public JsonResult doesURLExist(tPost post)
{
var allposts = _unitOfWork.PostRepository.Get();
if (allposts.Count(p => p.URLString == post.URLString) == 0)
{
return Json(true, JsonRequestBehavior.AllowGet);
}
if (allposts.Count(p => p.URLString == post.URLString && p.Id == post.Id) == 1)
{
return Json(true, JsonRequestBehavior.AllowGet);
}
return Json(false, JsonRequestBehavior.AllowGet);
}
Here is my model, passing an additional field "Id" this also gets put into my post object.
[RegularExpression("[a-z, 0-9]{1,50}", ErrorMessage = "URL String must be in lowercase")]
[Required(ErrorMessage = "Unique URL is required")]
[Remote("doesURLExist", "Post", AdditionalFields = "Id", HttpMethod = "POST", ErrorMessage = "URL already exists. Please enter a different URL.")]
public string URLString { get; set; }
Here is my HTML, all working perfect now.
<div class="form-group">
#Html.LabelFor(model => model.post.URLString, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.post.URLString, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.post.URLString, "", new { #class = "text-danger" })
</div>
</div>

Categories

Resources