not displaying validation messages while click on button in mvc4 - c#

i have created a login page i want it to display validation messages if user doesnt enter username and password on click of button,i have written code as below
Homecontroller.cs
public ActionResult Login()
{
// ViewBag.Message = "Your contact page.";
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(logintable p)
{
abEntities db = new abEntities();
List<sp_logindata_Result> data = db.sp_logindata(p.Username, p.Password).ToList();
Session["LogedUserID"] = data.First().UserID.ToString();
Session["UserNme"] = data.First().FullName.ToString();
int typeVal = data.First().Usertype;
if (typeVal == 1)
{
return RedirectToAction("page1");
}
else if (typeVal == 2)
{
return RedirectToAction("page2");
}
else
{
return RedirectToAction("Error");
}
return View(data);
}
logintable.cs
public partial class logintable
{
public logintable()
{
this.PerformanceDetails = new HashSet<PerformanceDetail>();
this.EvaluationDetails = new HashSet<EvaluationDetail>();
}
public string FullName { get; set; }
[Required(ErrorMessage = "Employee name is required")]
public string Username { get; set; }
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
public virtual ICollection<PerformanceDetail> PerformanceDetails { get; set; }
public virtual ICollection<EvaluationDetail> EvaluationDetails { get; set; }
}
login.cshtml
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div>
<fieldset>
<legend>Login</legend>
<div class="editor-field">
#Html.TextBoxFor(u => u.Username)
#Html.ValidationMessageFor(u => u.Username)
</div>
<div class="editor-label">
#Html.LabelFor(u => u.Password)
</div>
<div class="editor-field">
#Html.PasswordFor(u => u.Password)
#Html.ValidationMessageFor(u => u.Password)
</div>
<input type="submit" value="Log In" />
</fieldset>
</div>
}
what i am missing here so it is not displaying messages.

That won't happen automatically
You need to follow at minimum certain steps:
Add validation Rules to your Model [You already done]
Add the scripts that will take care of client side validation (unobstrusive validation) [Required].
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Add the bundle in BundleConfig.cs file, under App_Start folder
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.unobtrusive*",
~/Scripts/jquery.validate*"));

Related

How to save changes to a view model in C#?

I am currently reading values in a configuration file and setting the values to a view model. I am displaying them on the UI in textboxes. I want the user to be able to edit/change the value in the textbox and be able to hit a save button and for the changes to be saved to the view model and the configuration file. I understand there needs to be some type of Get/Post method in the controller but I'm not entirely sure how the controller should look. I am not connecting it to a database at all.
View:
#using (Html.BeginForm())
{
<fieldset>
<div class="row">
<div class="col-md-1">Logging Directory:</div>
<div class="col-md-2">#Html.EditorFor(model => Model.loggingDirectory)</div>
<div class="col-md-1">Archive Directory:</div>
<div class="col-md-2">#Html.EditorFor(model => Model.archiveDirectory)</div>
<div class="col-md-1">Time Between Alarms:</div>
<div class="col-md-2">#Html.EditorFor(model => Model.timeBetweenAlarms)</div>
<div class="col-md-1">Time to Archive Logs:</div>
<div class="col-md-2">#Html.EditorFor(model => Model.timeToArchive)</div>
<div class="col-md-1">Situator IP:</div>
<div class="col-md-2">#Html.EditorFor(model => Model.situatorIP)</div>
<div class="col-md-1 ">Situator Port:</div>
<div class="col-md-2 ">#Html.EditorFor(model => Model.situatorPort)</div>
<div class="col-md-1 ">Clean Up:</div>
<div class="col-md-2 ">#Html.EditorFor(model => Model.timeToCleanUp)</div>
<div class="col-md-1 ">Coorelation Zone:</div>
<div class="col-md-2">#Html.EditorFor(model => Model.coorelationZone)</div>
</div>
<div class="row submitButton">
<button class="btn btn-primary" type="submit">Save</button>
</div>
</fieldset>
}
View Model
public class ConfigurationViewModel
{
public string loggingDirectory { get; set; }
public string archiveDirectory { get; set; }
public string situatorIP { get; set; }
public string situatorPort { get; set; }
public string timeBetweenAlarms { get; set; }
public string timeToArchive { get; set; }
public string sightlogixIP { get; set; }
public string timeToCleanUp { get; set; }
public string coorelationZone { get; set; }
}
Controller:
public ActionResult Index()
{
ConfigurationViewModel cvm = new ConfigurationViewModel();
cvm.loggingDirectory = ConfigurationManager.AppSettings["loggingDirectoryPath"];
cvm.archiveDirectory = ConfigurationManager.AppSettings["archiveDirectoryPath"];
cvm.situatorIP = ConfigurationManager.AppSettings["SituatorIP"];
cvm.situatorPort = ConfigurationManager.AppSettings["SituatorPort"];
cvm.timeBetweenAlarms = ConfigurationManager.AppSettings["TimeIncrementBetweenalarmsInSeconds"];
cvm.timeToArchive = ConfigurationManager.AppSettings["timeIncrementForArchivingLogFilesInHours"];
cvm.sightlogixIP = ConfigurationManager.AppSettings["SightLogixIP"];
cvm.timeToCleanUp = ConfigurationManager.AppSettings["timeIncrementForCleaningUp"];
cvm.coorelationZone = ConfigurationManager.AppSettings["correlationZoneLengthInFeet"];
return View(cvm);
}
[HttpGet]
public ActionResult Edit()
{
return;
}
[HttpPost]
public ActionResult Edit()
{
return;
}
Pass view model in Get Edit method
[HttpGet]
public ActionResult Edit()
{
ConfigurationViewModel cvm = new ConfigurationViewModel();
cvm.loggingDirectory = ConfigurationManager.AppSettings["loggingDirectoryPath"];
cvm.archiveDirectory = ConfigurationManager.AppSettings["archiveDirectoryPath"];
cvm.situatorIP = ConfigurationManager.AppSettings["SituatorIP"];
cvm.situatorPort = ConfigurationManager.AppSettings["SituatorPort"];
//...
return View(cvm);
}
Send updated view model to post edit method and perform action on it
[HttpPost]
public ActionResult Edit(ConfigurationViewModel cvm)
{
ConfigurationManager.AppSettings["archiveDirectoryPath"] = cvm.archiveDirectory;
ConfigurationManager.AppSettings["SituatorIP"] = cvm.situatorIP;
ConfigurationManager.AppSettings["SituatorPort"]= cvm.situatorPort;
//...
return View(cvm);
}
And your razor view which will submit updated data to your Post Edit method
#using (Html.BeginForm("Edit", "Your controller", FormMethod.Post))
{
....
}

Validate login form

I wan't to validate a login form. I just wan't to check if the email field and password field are filled in. If not, an error message should display. I can't get it to work.
My actionresult Login:
[HttpPost]
public ActionResult Login(string email, string password, string returnUrl)
{
if (ModelState.IsValid)
{
try
{
User user = accountDal.GetAllUsers().FirstOrDefault(x => x.Email == email && x.Password == password);
if (user != null)
{
FormsAuthentication.SetAuthCookie(user.Email, false);
Response.Redirect(returnUrl, false);
}
return View();
}
catch
{
return View();
}
}
return View();
}
So as you can see, I check if the ModelState is valid.
Here is my login view:
#model ProjectInvoice.ViewModels.LoginViewModel
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<h3>Login</h3>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Password)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
</div>
<p>
<input type="submit" value="Create" />
</p>
}
And my ViewModel:
public class LoginViewModel
{
[Required]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[Display(Name = "Password")]
public string Password { get; set; }
}
If I use a breakpoint at the if (ModelState.IsValid) it says it is true, while this is not the case. Am I missing something, or am I doing something wrong?
You need to post back your model so the properties of your model can be validated
public ActionResult Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
....
Note also, when you return the view, you need to return the model
return View(model);
You need to have something like following:
public ActionResult Login(LoginViewModel loginViewModel, string returnUrl)
{
if (ModelState.IsValid)
{
try
{
User user = accountDal.GetAllUsers().FirstOrDefault(x => x.Email == loginViewModel.Email && x.Password == loginViewModel.Password);
if (user != null)
{
FormsAuthentication.SetAuthCookie(user.Email, false);
Response.Redirect(returnUrl, false);
}
return View();
}
catch
{
return View();
}
}
return View(loginViewModel);
}
The reason why it is not working is ModelState.IsValid validates your model against the data annotation applied to the LoginViewModel class's members.
You need to use data annotations. Like this:
public class LoginViewModel
{
[Required]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[Display(Name = "Password")]
public string Password { get; set; }
}
This will invalidate you're model state. And then, in the contriller, you return it to the View using something liek this:
return View(model)

textarea with writing code

I suffer from the following there
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Posts</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
<h4>Теги:</h4>
</div>
<div class="editor-field">
<input type="text" name="tags" value="#ViewBag.Tags"/><br />
</div>
#Html.HiddenFor(model => model.DateTime, new { #Value = System.DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss") })
#Html.ValidationMessageFor(model => model.DateTime)
<h5>body:</h5><textarea name="body" rows="10" cols="80" required >
</textarea><br />
<div class="editor-label">
#Html.LabelFor(model => model.Avtor)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Avtor)
#Html.ValidationMessageFor(model => model.Avtor)
</div>
<p>
<input type="submit" value="save" />
</p>
</fieldset>
}
in
public ActionResult Create([Bind(Include = "Id,Title,DateTime,Body,Avtor")] Posts post, string tags, string body)
{
if (ModelState.IsValid)
{
tags = tags ?? string.Empty;
string[] tagNames = tags.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string tagName in tagNames)
{
post.Tags.Add(GetTag(tagName));
}
post.Body = body;
db.Posts.Add(post);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(post);
}
public partial class Posts
{
public Posts()
{
this.Comments = new HashSet<Comments>();
this.Tags = new HashSet<Tags>();
}
public int Id { get; set; }
[Required]
[StringLength(64, MinimumLength = 1)]
public string Title { get; set; }
public System.DateTime DateTime { get; set; }
[Required]
[AllowHtml]
public string Body { get; set; }
[Required]
[StringLength(64, MinimumLength = 1)]
public string Avtor { get; set; }
public virtual ICollection<Comments> Comments { get; set; }
public virtual ICollection<Tags> Tags { get; set; }
}
if the user dials in plain text in textarea, it's okay, but there is a need to add the code text. It makes <pre> and <code>but it can only do I have in the program, not the user in textarea. Strictly speaking how to do so in tehtarea could write code and save it in the database and not get an error using <a> <script> and that they could be seen in the text. so the spacecraft itself is implemented on this site. Thanks in advance.
Create a strongly typed model to accept the data posted to the server, use the data annotation AllowHtml to accept HTML as input:
public class SomeViewModel
{
Posts Post { get; set; }
[AllowHtml]
public string Body { get; set; }
}
Then change the controller to
public ActionResult Create(SomeViewModel model)
{
if (ModelState.IsValid)
{
model.Post.Body = model.Body;
db.Posts.Add(model.Post);
db.SaveChanges();
return RedirectToAction("Index");
}
return RedirectToAction("Index");
}
Also try adding this to the following location in your web.config file just above the pages section:
<system.web>
...
<httpRuntime requestValidationMode="2.0" enableVersionHeader="false" />
<pages...
...
</system.web>
Changing the request validation mode will essentially only validation pages rather than every http request. You can read more about it here on MSDN HttpRuntimeSection.RequestValidationMode
Use AllowHTMLAttribute
see this MSDN
This will only allow html for that specific field in your viewmodel but not the whole thing.
or alternatively you can do:
[ValidateInput(false)]
public ActionResult someAction(SomeViewModel model)
{
//Your code to handle the control
}
EDIT: Notice that your textarea is not part of the model in your HTML, can you change that <textarea name="body".... line to:
#Html.TextArea("body", new { rows=10, columns=80 })
After that your body textarea element should be able to capture HTML elements to your controller.

DropDownList in ASP.NEt MVC Edit method

Good day,
I'm write asp.net mvc3 project with bundle of SQL Server 2012 & EF, I'm use dropdownlist for create & update entry in database. Everything works fine when I add page, but when I'm try to Edit it's unable to save changes. I was try to take brackpoint and in debugging mode Inner exception told that
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
This is my code:
[Table("Pages", Schema = "myprojectname")]
[Bind(Exclude = "PageId")]
public class Page
{
public int PageId { get; set; }
public string PageContent { get; set; }
public int PageTitleId { get; set; }
public virtual PageTitle PageTitle { get; set; }
}
[Table("PageTitles", Schema = "myprojectname")]
public class PageTitle
{
public int PageTitleId { get; set; }
public string Title { get; set; }
public List<Page> Pages { get; set; }
}
public DbSet<Page> Pages { get; set; }
public DbSet<PageTitle> PageTitles { get; set; }
public ActionResult PageEdit(int id)
{
Page page = context.Pages.Find(id);
ViewBag.PageTitleId = new SelectList(context.PageTitles, "PageTitleId", "Title", page.PageTitleId);
return View(page);
}
[HttpPost]
[ValidateInput(false)]
public ActionResult PageEdit(Page page)
{
try
{
if (ModelState.IsValid)
{
context.Entry(page).State = EntityState.Modified;
context.SaveChanges();
return RedirectToAction("Index", "Administrator");
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable to save changes. Please try again");
}
ViewBag.PageTitleId = new SelectList(context.PageTitles, "PageTitleId", "Title", page.PageTitleId);
return View(page);
}
#model BalticCenter.Web.Models.Entities.SitePages.Page
#{
ViewBag.Title = "PageEdit";
Layout = "~/Views/Shared/_AdministratorLayout.cshtml";
}
<h2>PageEdit</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Page</legend>
#Html.HiddenFor(x => x.PageId)
<div class="editor-label">
#Html.LabelFor(model => model.PageTitleId, "PageTitle")
</div>
<div class="editor-field">
#Html.DropDownList("PageTitleId", String.Empty)
#Html.ValidationMessageFor(model => model.PageTitleId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PageContent)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.PageContent)
#Html.ValidationMessageFor(model => model.PageContent)
</div>
<p>
<input type="submit" value="Edit" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
I don't see my mistake. Any ideas?
You have your class Page decorated with [Bind(Exclude = "PageId")]
This means that when you set EntityState to Modified the Entity have no primeary key (id)
context.Entry(page).State = EntityState.Modified;
context.SaveChanges();
And there fore the database can't save the changes

Model (complex type) won't submit to action

I have some problem posting a form with 'complex type' model:
I have a Model:
public class CircleEditViewModel
{
[Key]
public int CircleId { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
public bool IsSystem { get; set; }
public class UserInCircle
{
public UserInCircle(User user)
{
this.UserId = user.UserId;
FullName = user.FullName;
}
public int UserId { get; set; }
public byte[] Picture { get; set; }
public string FullName { get; set; }
public bool isInCircle { get; set; }
}
public List<UserInCircle> Users { get; set; }
}
My first problem was that at post event, my Users where null.. so i followed a few posts on here (like MVC- Model Binding on a Complex Type) to use a for instead of a foreach,but since i did so, my form won't post anymore:
View:
#model Wims.Website.ViewModels.CircleEditViewModel
<script type="text/javascript">
$(document).ready(function () {
$.validator.unobtrusive.parse('form');
});
</script>
#using (Ajax.BeginForm(Html.ViewContext.RouteData.Values["Action"].ToString(), null, new AjaxOptions { HttpMethod = "POST", OnSuccess = "SaveDone(data)" }, new { id = "editform" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Circle</legend>
#Html.Label(DateTime.Now.ToString());
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</fieldset>
if (Model.Users != null)
{
for (int i = 0; i < Model.Users.Count; i++)
{
<div class="userDetail">
<div>
<div>
#Html.DisplayFor(model => Model.Users[i].isInCircle);
</div>
<div class="iconDiv">
#Html.Image("~/Content/Images/defaultUser.jpg", Model.Users[i].FullName, null);
</div>
<div>
#Html.TextBoxFor(model => Model.Users[i].FullName)
#Html.HiddenFor(model => Model.Users[i].UserId)
</div>
</div>
</div>
<div style="clear: both"></div>
}
}
#Html.GenerateSecureDataControls(model => model.CircleId)
<input type="submit" value="Save" />
}
My view is rendered as a partial loaded thru ajax (not sure it makes any difference here).
Any idea why it won't post? If i remove all the '[]' like 'Users[0].FullName' to Users0.FullName i will post, but of course it won't be bound.
Thanks for your help
Edit just in case needed: Action:
[HttpPost]
public ActionResult Edit(CircleEditViewModel circleData, FormCollection collection)
{
if (ModelState.IsValid)
{
using (var logic = new CircleLogic())
{
Circle circle = logic.GetCircleById(circleData.CircleId, WebMatrix.WebData.WebSecurity.CurrentUserId);
if (circle == null)
{
return HttpNotFound();
}
else
{
circle.Name = circleData.Name;
logic.UpdateCircle(circle, GetSelectedUser(collection));
}
return PartialView("_CircleAndUsers", GetData(logic, circle.CircleId));
}
}
return this.Json(new { success = false, viewdata = RenderRazorViewToString("_CircleAndUsers", circleData) });
}
Pablo Romeo was right, i added a default ctor and it worked.

Categories

Resources