Data annotation not displaying error message - c#

I want to use data annotations in my app and the problem is when I click in submit button and don't fill the required field I don't see any error message and it submits. In the controller, the model.state works fine, but I think I should see the error message.
The model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace ValidationTest.Models
{
public class User
{
[Required(ErrorMessage = "Enter your name.")]
public string Name { get; set; }
public string Lastname { get; set; }
}
}
The View:
#model ValidationTest.Models.User
#{
ViewBag.Title = "Index";
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
#using (Html.BeginForm("Record", "Home"))
{
#Html.Label("Name:")
#Html.TextBoxFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
<br />
#Html.Label("Lastname:")
#Html.TextBoxFor(m => m.Lastname)
#Html.ValidationMessageFor(m => m.Lastname)
<input type="submit" value="Record" />
}
</body>
</html>
The controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ValidationTest.Models;
namespace ValidationTest.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Record(User usr)
{
if (ModelState.IsValid)
{
return Content("It Worked!");
}
return RedirectToAction("Index");
}
}
}
In Scripts folder inside the ASP.NET MVC project i have:
bootstrap.js
bootstrap.min.js
jquery-3.2.1.intellisense.js
jquery-3.2.1.js
jquery-3.2.1.min.js
jquery-3.2.1.min.map
jquery-3.2.1.slim.js
jquery-3.2.1.slim.min.js
jquery-3.2.1.slim.min.js
modernizr-2.6.2.js

You will have to add JavaScript script references of jquery.validate.min.js and jquery.validate.unobtrusive.min.js for client side validation to work.

Move return RedirectToAction("Index"); inside if (ModelState.IsValid) condition.
return view(); should be added outside if condition.

Related

View() ASP.NET Core

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Csharp_ASPNetCore.Pages.Shared
{
public class ExampleController : Controller
{
public ExampleController()
{
}
[HttpGet]
[Route("/example/")]
public IActionResult Index()
{
return View();
}
[HttpPost]
[Route("/example/")]
public IActionResult Index(string someValue)
{
string buttonClicked = "";
if (HttpContext.Request.Form.ContainsKey("btnOne"))
{
buttonClicked = "btnOne";
int a = 1;
int b = 2;
int c = a + b;
// return View("AAAAAA");
}
else if (HttpContext.Request.Form.ContainsKey("btnTwo"))
{
buttonClicked = "btnTwo";
}
return View("Index");
}
}
}
The last View("Index") command doesn't work, returning this error:
"An unhandled exception occurred while processing the request. InvalidOperationException: The view 'Index' was not found. The following locations were searched: /Views/Example/Index.cshtml /Views/Shared/Index.cs
Following I report the Index.cshtml where there are the buttons (the name of the controller is ExampleController.cs). Thanks!
#page
#model IndexModel
#{
ViewData["Title"] = "Home page";
}
<div>
<form asp-controller="example" asp-action="Index">
<label>Value:</label>
<input name="someValue" type="text" maxlength="10"/>
<button name="btnOne" type="submit" class="btn btn-default">Click One</button>
<button name="btnTwo" type="submit" class="btn btn-default">Click Two</button>
</form>
</div>

TryUpdateModel Asp.Net MVC is not working

I am trying to learn how to use TryUpdateModel but I cannot get it to work, you can find my code below:
Controller Side
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace EFW6.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
private WorkFlowContext context = new WorkFlowContext();
public ActionResult Index()
{
return View();
}
[HttpPost]
public string UploadFile(FormCollection form)
{
Files file = new Files();
if (TryUpdateModel(file, form.ToValueProvider()))
{
return "True " + file.filePath;
}
else
{
return "False";
}
}
}
}
View Side
#{
ViewBag.Title = "index";
}
<h2>#Model</h2>
<form method="post" action="Home/UploadFile">
<input type="text" name="filePath">
<input type="submit">
</form>
Model Class
class Files
{
public string filePath;
}
When I return the value of the file path it returns nothing while it returns the value True for as a result for the operation.
the problem is that you I am using field instead of property in the Files Class
You have to change it to be like this
class Files
{
public string FilePath { get; set; }
}

MVC 4. ModelState.IsValid always return true

I don't understand why ModelState.isValid give me in all the ways. I set something in the email returns true and I pùt empty field, it returns true too. My question ism, what do I have to do to return true when the field is empty and nothing whn I wrote the email?
I have the next view file:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<div style="padding-top:5px;clear:both;"></div>
<% using (Html.BeginForm()) { %>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Email usuario</legend>
<div class="editor-field">
<%: Html.TextBoxFor(m => m.Email) %>
<%: Html.ValidationMessageFor(m => m.Email) %>
</div>
<input type="submit" value="Enviar Email" />
</fieldset>
<% } %>
<div style="padding-top:5px;clear:both;"></div>
</asp:Content>
The Controller is:
//
// GET: /Account/EmailRequest
public ActionResult EmailRequest()
{
return View();
}
[HttpPost]
public ActionResult EmailRequest(string email)
{
if (ModelState.IsValid)
{
// save to db, for instance
return RedirectToAction("AnotherAction");
}
return View();
}
My model class is:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Web.Mvc;
using System.Web.Security;
namespace PortalClient.Models
{
public class EmailRequest
{
[Required(ErrorMessage = "required")]
public string Email { get; set; }
}
}
Change the signature of your post action from string email to EmailRequest model and then check the state. e.g.
[HttpPost]
public ActionResult EmailRequest(EmailRequest model)
{
if (ModelState.IsValid)
{
// save to db, for instance
return RedirectToAction("AnotherAction");
}
return View();
}
You need to bind a view model to your view.
Change your EmailRequest model to something more descriptive like:
public class EmailRequestViewModel
{
[Required(ErrorMessage = "Required")]
public string Email { get; set; }
}
Your get action method would look something like:
public ActionResult EmailRequest()
{
EmailRequestViewModel viewModel = new EmailRequestViewModel();
return View(viewModel);
}
Your post action method:
public ActionResult EmailRequest(EmailRequestViewModel viewModel)
{
// Check for null view model
if (!ModelState.IsValid)
{
return View(viewModel);
}
// Do whatever you need to do
return RedirectToAction("List");
}
And then your view. Please excuse the ASP.NET MVC 4 code, MVC 2 is prehistoric :) This is just part of your view:
#model YourProject.ViewModels.EmailRequestViewModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(x => x.Email)
#Html.ValidationMessageFor(x => x.Email)
}
I hope this helps.
you need to bind your model with binder first to have ability to chek it by Modelstat.IsValid
public ActionResult EmailRequest()
{
EmailRequest email = new EmailRequest();
TryUpdateModel(email);
if (ModelState.IsValid)
{
// save to db, for instance
return RedirectToAction("AnotherAction");
}
return View();
}

C# pre-populating textarea from database

I have a small website with a Homepage which displays x2 paragraphs of text. These paragraphs are populated from a single record in a database containing 3 fields ("ID", "para1" and "para2"). This record is updated via a form which contains x2 textareas (assigned to update "para1" and "para2"), allowing me to type into the textarea, click "update" and then the two paragraphs on the Homepage will update to reflect the new text.
To navigate to the form page that contains the textareas from the homepage I click an "admin" link which takes me to a logon page, I enter username and password and click "login" and this forwards me on to the "update" page.
What I'd like, is the x2 textarea inputs to be pre-populated with the data stored in the "para1" and "para2" fields in the database table. This way, if someone wanted to make a minor edit to either of the paragraphs on the homepage then they won't need to re-type the whole thing from scratch.
I'm using C# Razor in Microsoft Visual Web Developer Express. I am a total beginner at not just this, but any form of development work, so I'm learning as I'm going, please be gentle :-)
Code examples below:
(the View page):
#model DFAccountancy.Models.Data
#{
ViewBag.Title = "Update";
}
<h2>Update</h2>
<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)
<fieldset>
<legend>Data</legend>
<div class="editor-label">
#Html.LabelFor(model => model.para1)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.para1, new { cols = 75, #rows = 5 })
#*#Html.EditorFor(model => model.para1)*#
#Html.ValidationMessageFor(model => model.para1)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.para2)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.para2, new { cols = 75, #rows = 5 })
#*#Html.EditorFor(model => model.para2)*#
#Html.ValidationMessageFor(model => model.para2)
</div>
<p>
<input type="submit" value="Update" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
(the Model):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
namespace DFAccountancy.Models
{
public class Data
{
[DataType(DataType.MultilineText)]
public int ID { get; set; }
public string para1 { get; set; }
public string para2 { get; set; }
}
public class DataDBContext : DbContext
{
public DbSet<Data> Data { get; set; }
}
}
(the Controller):
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DFAccountancy.Models;
namespace DFAccountancy.Controllers
{
public class DataController : Controller
{
private DataDBContext db = new DataDBContext();
//
// GET: /Data/
public ViewResult Index()
{
return View(db.Data.ToList());
}
//
// GET: /Data/Details/5
public ViewResult Details(string id)
{
Data data = db.Data.Find(id);
return View(data);
}
//
// GET: /Data/Update/5
public ActionResult Update()
{
return View();
}
//
// POST: /Data/Update/5
[HttpPost]
public ActionResult Update(Data data)
{
if (ModelState.IsValid)
{
data.ID = 1; //EF need to know which row to update in the database.
db.Entry(data).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
return View(data);
}
}
}
You just need to update your Update method to include passing in an Id
//
// GET: /Data/Update/5
public ActionResult Update()
{
Data data = db.Data.Find("1");
return View(data);
}
In addition the link to the update method will need to be updated to pass that Id in as well. Assuming you're using the standard list template for MVC.
<td>
#Html.ActionLink("Update", "Update") |
...
</td>

Getting and dealing with the Entered data in MVC - Simple

I have some questions regarding my MVC learning curve
Goal:
I want to get the txtMHM entered text
after the btnStat is pushed and show the entered text via a label or span or ...
The View Model you should use (simplified):
public class YourViewModel
{
public string TextEntered { get ; set ; }
}
The View:
#model YourViewModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.TextEntered)
<br />
<input id="btnStat" type="submit" value="MHM" />
}
#Html.LabelFor(m => m.TextEntered)
The Controller Action method:
[HttpPost]
public ActionResult ChangeLabelText(YourViewModel yourViewModel)
{
return View(yourViewModel);
}
Your Altered Code
index.cshtml
#model MVCTest1.Models.EnteredTextModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.TextEntered)
<br />
<input id="btnStat" type="submit" value="MHM" />
}
#Html.LabelFor(m => m.TextEntered)
The Model
namespace MVCTest1.Models
{
public class EnteredTextModel
{
public string TextEntered { get; set; }
}
}
The HomeController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MVCTest1.Models ;
namespace MVCTest1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
[HttpPost]
public ActionResult Index(EnteredTextModel theModel)
{
return View(theModel);
}
public ActionResult About()
{
return View();
}
}
}
Sypress,
Best practice would be to use a viewmodel for your action. However, at a very simple level, based on exactly what you have above, you could use the viewbag object to pass back the input value. without further ado, the frig, i mean code :):
Controller actions:
[HttpGet]
public ActionResult ChangeLabelText()
{
return View();
}
[HttpPost]
public ActionResult ChangeLabelText(FormCollection formCollection)
{
ViewBag.LastNameEntered = formCollection["txtName"];
return View();
}
View stuff (assumes that the view is named ChangeLabelText.cshtml of course):
#{
ViewBag.Title = "ChangeLabelText";
}
<h2>ChangeLabelText</h2>
<form action="ChangeLabelText" method="post">
<input id="txtMHM" type="text" name="txtName" value="" />
<input id="btnStat" type="submit" value="Post" />
<br />
#Html.Label("Entered Text");
<span id="spnEnteredText">#ViewBag.LastNameEntered </span>
</form>
and the above is called as such http://localhost:xxxx/Home/ChangeLabelText (where xxxx is the port number of your dev server)
I would add that this would NOT be the way that I would approach this to be honest, but is my direct response to your example. go for sharks' example using the viewmodel.
good luck
[EDIT] - I've updated my answer now that I'm at a machine, so the above should work as intended.

Categories

Resources