How to check if any model item is assigned a value in MVC? - asp.net-mvc

I have a model which have properties.And, i want to check that if any model item has some value or not.Also,no property is set to mandatory or optional using data-annotations.If no property is assigned and any value then i should set some model error e.g "Please specify some search criteria."
#using (Html.BeginForm("GetAdvanceSearchData", "Home", FormMethod.Post)){
<div class="rTableCell" style="border:none !important">
#Html.TextBoxFor(m => m.MessageStatus, new { placeholder = Html.DisplayNameFor(n => n.MessageStatus), #class = "fieldtextbox", #style = "height: 25px !important" })
#Html.ValidationMessageFor(m => m.MessageStatus)
</div>
<div class="rTableCell" style="border:none !important">
#Html.TextBoxFor(m => m.RequestType, new { placeholder = Html.DisplayNameFor(n => n.RequestType), #class = "fieldtextbox", #style = "height: 25px !important" })
#Html.ValidationMessageFor(m => m.RequestType)
</div>
<div class="rTableCell" style="border:none !important">
</div>
<div class="rTableCell" style="border:none !important">
<p class="submit">
<button type="submit" name="submit">
<i class="fa fa-arrow-right" aria-hidden="true"></i>
</button>
</p>
</div>
}
These are only few properties for the model.

In action method GetAdvanceSearchData you can do your own validity checks, in addition to validation attributes, or instead of them.
If you add an entry to ModelState then ModelState.IsValid will become false, and the added entry will show in the output of Html.ValidationMessageFor(...) or Html.ValidationSummary().
Example:
[HttpPost]
public ActionResult GetAdvanceSearchData(YourModel vm)
{
if (vm == null || (string.IsNullOrEmpty(vm.MessageStatus) && string.IsNullOrEmpty(vm.RequestType)))
{
ModelState.AddModelError("", "Please specify some search criteria")
// Using "" as Key will only show when you use #Html.ValidationSummary().
// Using "myErr" as Key will show when you use #Html.ValidationMessage("myErr").
// Using a property name as Key will show it next to the property if you use #Html.ValidationMessageFor(m => m.property).
}
if (ModelState.IsValid)
{
var results = ...
return View("ResultsView", results);
}
else
{
return View(vm);
}
}

Related

How can i pass multiple radio button values to controller in ASP.NET MVC?

I've a model that contains 3 tables in my view.
public class InExam
{
public AutoTests TheTest { get; set; }
public List<InTest> TheQuestions { get; set; }
public IEnumerable<Result> SingleQuee { get; set; }
}
First one made to get the detailed page, like "admin/AutoTests/id"
Second one made to get a list of questions linked to the page
Third one is to save radio button strings to post it back into the controller
my plan is to get (say) 20 questions that are linked with the detailed page, Adding 4 radio buttons for each question, and post back every selected button to the controller.
my view form :
#using (Html.BeginForm("Test", "Exams", new { id = Model.TheTest.id }, FormMethod.Post))
{
foreach (var item in Model.TheQuestions)
{
Kafo.Models.Result singleQuee = Model.SingleQuee.Where(x => x.Question == item.Question).FirstOrDefault();
<div class="container" style="padding-top:50px;direction:rtl;">
<h4 style="text-align:right;font-weight:bold;">#item.Question</h4>
<div class="container">
<div class="row" style="direction:rtl;">
<div class="col-lg-7" style="text-align:right;margin-right:10px;">
<div class="row">
#Html.RadioButtonFor(x => singleQuee.Question, new { #class = "form-control dot", #Name = singleQuee.Question, #Value = "1" })
<h5 style="padding-top:3px;padding-right:8px;">#item.RightAnswer</h5>
</div>
</div>
<div class="col-lg-7" style="text-align:right;margin-right:10px;">
<div class="row">
#Html.RadioButtonFor(x => singleQuee.Question, new { #class = "form-control dot", #Name = singleQuee.Question, #Value = "2" })
<h5 style="padding-top:3px;padding-right:8px;">#item.Answer2</h5>
</div>
</div>
<div class="col-lg-7" style="text-align:right;margin-right:10px;">
<div class="row">
#Html.RadioButtonFor(x => singleQuee.Question, new { #class = "form-control dot", #Name = singleQuee.Question, #Value = "3" })
<h5 style="padding-top:3px;padding-right:8px;">#item.Answer3</h5>
</div>
</div>
<div class="col-lg-7" style="text-align:right;margin-right:10px;">
<div class="row">
#Html.RadioButtonFor(x => singleQuee.Question, new { #class = "form-control dot", #Name = singleQuee.Question, #Value = "4" })
<h5 style="padding-top:3px;padding-right:8px;">#item.Answer4</h5>
</div>
</div>
#Html.HiddenFor(m => singleQuee.Question)
</div>
</div>
</div>
}
<button class="btn botton" type="submit" onclick="return confirm('');">END</button>
}
i used this line "Kafo.Models.Result singleQuee = Model.SingleQuee.Where(x => x.Question == item.Question).FirstOrDefault();" in my view because i can't use tuple foreach ( C# ver. 5 )
This is my controller code :
[HttpGet]public ActionResult Test(int? id)
{
using (KafoEntities db = new KafoEntities())
{
InExam model = new InExam();
model.TheTest = db.AutoTests.Where(x => x.id == id).FirstOrDefault();
model.TheQuestions = db.InTest.Where(x => x.UserEmail == currentUser.Email && x.ExamId == model.TheTest.id).OrderByDescending(x => x.id).Take(Convert.ToInt32(model.TheTest.QuestionsNumber)).ToList();
model.SingleQuee = db.Result.ToList();
return View(model);
}
}
[HttpPost]
public ActionResult Test(int? id, List<Result> singleQuee)
{
using (KafoEntities db = new KafoEntities())
{
int result = 0;
foreach (Result item in singleQuee)
{
Result sets = db.Result.Where(x => x.id == item.id).FirstOrDefault();
sets.Question = item.Question;
db.SaveChanges();
var check = db.InTest.Where(x => x.Question == item.Question).FirstOrDefault();
if (check != null)
{
if (item.Question == "1")
{
result++;
}
}
}
return RedirectToAction("Results", "Exams", new { Controller = "Exams", Action = "Results", id = done.id });
}
}
I first save the new string that came from the radio button value into the result record, then i call it back in the if condition to check it's value
The problem here is i get a
Object reference not set to an instance of an object.
when i post the test, it means that the list is empty, so i need to know what makes the radio buttons not working,
Thanks.
If you want to bind a List of object in Mvc, you should name the controller like "ModelName[indx].PropertyName". In your case it should be "singleQuee[0].Question".
Code Sample
var Indx = 0;
foreach (var item in Model.TheQuestions)
{
.....
var radioName = $"singleQuee[{Indx}].Question";
<div class="col-lg-7" style="text-align:right;margin-right:10px;">
<div class="row">
<input type="radio" name="#radioName" value="1" />
<h5 style="padding-top:3px;padding-right:8px;">#item.RightAnswer</h5>
</div>
</div>
.....
}
Action Method

Model Data not binding to textboxfor after insertion in MVC

I'm facing a problem in mvc 4, i have create action method where i insert the data in db and then return model to View but the model data not bind to hidden Field like Id and Voucher number,
in other fields data binds properly but the issue is with these Id and VoucherNum, Id is primary key and VoucherNum is Unique.
I have mentioned the code and html.
Code:
[HttpPost]
public ActionResult Create(Payment payment)
{
payment.VoucherNum = db.Payments.Count() + 1;
Ledger ledger = new Ledger();
ledger.CusId = payment.CustomerId;
ledger.Date = payment.Date;
ledger.Remarks = payment.Remarks;
ledger.Type = payment.Type;
string negativeAmount;
negativeAmount = "-" + payment.Amount;
ledger.Amount = Convert.ToInt32(negativeAmount);
ledger.IsActive = true;
payment.IsActive = true;
db.Payments.Add(payment);
db.Ledgers.Add(ledger);
db.SaveChanges();
ViewBag.CustomerId = new SelectList(db.Customers.ToList()
.Select(x => new { Id = x.Id, CustomerCode = x.Name + "-" + x.CustomerCode }
), "Id", "CustomerCode", payment.CustomerId);
var model = db.Payments.Find(payment.Id);
return View(model);
}
<h2>Payments</h2>
<hr />
<div class="row">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="col-md-4">
<div class="form-group">
<label class="control-label">Vocher#</label>
#Html.TextBoxFor(model => model.VoucherNum, new { #class = "form-control", #readonly="true"})
#Html.HiddenFor(model=>model.Id)
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label class="control-label">Customer</label>
#Html.DropDownList("CustomerId", (IEnumerable<SelectListItem>)ViewBag.CusId, "--Select Customer--", new { #class = "form-control" })
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label class="control-label">Date</label>
#Html.TextBoxFor(model => model.Date, new { #class = "form-control", #id = "date"})
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label class="control-label">Amount</label>
#Html.TextBoxFor(model => model.Amount, new { #class = "form-control" })
</div>
<div class="form-group">
<label class="control-label">Type</label>
#Html.TextBoxFor(model => model.Type, new { #class = "form-control" })
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<label class="control-label">Remarks</label>
#Html.TextAreaFor(model => model.Remarks, new { #class = "form-control", #rows = "5" })
</div>
<input type="submit" value="Payment Receive" class="btn btn-primary pull-right" />
</div>
}
</div>
Because the helper method will look in to the model state dictionary first to populate the value of the input. The model state dictionary currently has null value for the VoucherNum before you saved it, and the helper method will use this value to generate the value of the input field.
To fix this, you can explicitly clear the model state dictionary before returning to the view,
db.Payments.Add(payment);
db.SaveChanges();
ModelState.Clear();
var p = db.Payments.Find(model.Id);
return View(p);
Or even better, follow the PRG pattern. With the Post-Redirect-Get pattern, After successfully updating the database, you will return a Redirect Response back to the client and the client will issue a totally new GET request to the server.
In your case, You can use RedirectToAction to return a 302 response.
db.SaveChanges();
return RedirectToAction("Edit",new {id=payment.Id});
This will tell the browser to issue a new GET request for Edit action method with the new id in the request url. Your GET action method will use this id and get the entity from db and return it.
public ActionResult Edit(int id)
{
var model = db.Payments.Find(id);
return View(model);
}
I strongly recommend you using the PRG pattern.

Action in controller received empty model from Html.BeginForm - ASP.NET MVC

I have stucked for 3 days. There is nowhere I had been looking for this problem. When I submit the form, Controller action method doesnt get the model.
My base view Login.cshtml
#{
string durum = ViewBag.Style;
switch (durum)
{
case "Login":
Html.RenderAction("_Login", "Dashboard");
break;
case "LostPassword":
Html.RenderAction("_LostPassword", "Dashboard");
break;
case "RegisterForm":
Html.RenderAction("_RegisterForm", "Dashboard");
break;
default:
Html.RenderAction("_Login", "Dashboard");
break;
}
}
One of my partial view _LostPassword.cshtml
#model HaberSitesi._Entities.Kullanici
#using (Html.BeginForm("LostPassword", "Dashboard", FormMethod.Post, new { #class = "forget-form", #style = "display:block" }))
{
if (TempData["ForgotPassword"] != null)
{
<div class="alert alert-warning ">
<button class="close" data-close="alert"></button>
<span>#TempData["ForgotPassword"]</span>
</div>
}
<h3>Şifrenizi mi unuttunuz ?</h3>
<p> Şifrenizi almak için lütfen E-Posta adresinizi giriniz. </p>
<div class="form-group">
<div class="input-icon">
<i class="fa fa-envelope"></i>
#Html.TextBoxFor(x => x.EPosta, new { #class = "form-control placeholder-no-fix", #type = "email", #autocomplete = "off", #placeholder = "Eposta", Name = "email" })
#Html.ValidationMessageFor(x => x.EPosta)
</div>
</div>
<div class="form-actions">
#Html.ActionLink("Geri Dön", "Login", "Dashboard", new { }, new { #type = "button", #id = "back-btn", #class = "btn grey-salsa btn-outline" })
<button type="submit" class="btn green pull-right"> Gönder </button>
</div>
}
And the action in controller DashboardController.cs
public ActionResult LostPassword()
{
VeriTransfer();
return View("Login");
}
[HttpPost]
public ActionResult LostPassword(Kullanici kullanici)
{
string kullaniciEposta = kullanici.EPosta;
Kullanici user = _kullaniciBll.Get(kullaniciEposta);
if (user != null)
{
TempData["ForgotPassword"] = "Şifreniz e-posta adresinize gönderildi.";
}
else
{
TempData["ForgotPassword"] = "Kayıtlarımızda e-posta adresiniz bulunamadı";
}
VeriTransfer();
return View("Login");
}
When I click submit button, I cant get any data (Kullanici kullanici) in controller. Every property comes null or default data value from model.
Note: Maybe my codes could have some other mistakes which are irrelevant with my problem. I just wonder why I get empty model. Thanks at least you have read my problem.
Your property is called EPosta but you changed the name of it to Name="email".So when the POST action happens it sends a property called email to the controller action and your Kullanici object expects a property called EPosta
Both of these will fix your problem:
Change Name="email" to Name="EPosta" or
Remove Name="email" completely
But like Stephen said it's better to remove it completely,because if you rename your property to EPosta2 in future and forget to change the name to Name="EPosta2" your POST will no longer work

Displaying Invalid user name or password using MVC Validation

I am using MVC validation to check if use name and password exit in database or not. ModelState.IsValid is true always even when I did not find any matching user.
if (objModel != null)
{
if (ModelState.IsValid && Membership.ValidateUser(objUsersModel.UserName, objUsersModel.Password))
{
Profile.Initialize(objUsersModel.UserName.Trim(), true);
FormsAuthentication.SetAuthCookie(objUsersModel.UserName, false);
return RedirectToAction("Index", "Home");
}
}
How can I set this to false and set the values for error message in mvc view. Here is my MVC view .
<form role="form">
<div class="form-group">
<label for="exampleInputEmail1">User Name </label>
<i class="fa fa-user"></i>
#Html.TextBoxFor(m => m.UserName, new { maxlength = 50, #class = "form-control" })
#Html.ValidationMessageFor(u => u.UserName)
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<i class="fa fa-lock"></i>
#Html.PasswordFor(m => m.Password, new { maxlength = 50, #class = "form-control" })
#Html.ValidationMessageFor(u => u.Password)
</div>
<div class="form-actions">
<label class="checkbox"> <input type="checkbox" class="uniform" value=""> Remember me</label>
<button type="submit" class="btn btn-danger">Submit</button>
</div>
</form>
You need to add a ModelState error and return the view if the user name and password are not valid
if (!ModelState.IsValid)
{
return View(yourModel);
}
if (!Membership.ValidateUser(objUsersModel.UserName, objUsersModel.Password)
{
ModelState.AddModelError(string.Empty, "The user name or password is incorrect");
return View(yourModel);
}
....
return RedirectToAction("Index", "Home");
and in the view, include
#Html.ValidationSummary(true)
to display the message

Retrieving dropdown values from partial view during post method

I need to get the selected dropdown value from partial view and included in the CategoryID in the Book class...
[Authorize]
public PartialViewResult GetAllCategory()
{
ProcessSVC.Category newCategory = new ProcessSVC.Category();
newCategory.ChildCategories = obj1.GetAllCategories(String.Empty);
return PartialView(newCategory);
}
GetAllCategory.cshtml (PartialView)
#model MvcAdminTemplate.ProcessSVC.Category
#Html.DropDownListFor(m => m.ParentID, new SelectList(Model.ChildCategories, "ID", "DisplayName"), new { #class = "form-control" })
Create View:
[Authorize]
[HttpPost]
public ActionResult Create()
{
MvcAdminTemplate.ProcessSVC.Book oBook = new ProcessSVC.Book();
return View(oBook);
}
Create.cshtml
#model MvcAdminTemplate.ProcessSVC.Book
#{
ViewBag.Title = "Create";
}
#Html.Partial("_LeftMenu")
<!-- content -->
<h2>Create</h2>
<div class="col-md-10">
#using (Html.BeginForm("Create", "Books", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="row">
<div class="bootstrap-admin-no-table-panel-content bootstrap-admin-panel-content collapse in">
<form class="form-horizontal">
<fieldset>
<legend>Add Book</legend>
<div class="form-group">
<div class="col-lg-2">
#Html.LabelFor(m => m.BookName, new { #class = "control-label" })
</div>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.BookName, new { #class = "form-control", type = "text" })
<p class="help-block"> </p>
</div>
</div>
<div class="form-group">
<div class="col-lg-2">
#Html.LabelFor(m => m.Description, new { #class = " control-label" })
</div>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.Description, new { #class = "form-control ", type = "text" })
<p class="help-block"> </p>
</div>
</div>
<div class="form-group divCategory">
<div class="col-lg-2">
#Html.Label("Parent Category", new { #class = " control-label" })
</div>
<div class="col-lg-10">
#Html.HiddenFor(m => m.BookId, new { #class = "hdn-id" })
#Html.Action("GetAllCategory","Books")
<span class="help-block"> </span>
</div>
<button type="submit" class="btn btn-primary">Save changes</button>
<button type="reset" class="btn btn-default">Cancel</button>
</div>
</fieldset>
</form>
</div>
</div>
}
After submission of the above form i need to get Book attributes and Category "Selected Category".
[Authorize]
[HttpPost]
public ActionResult Create(ProcessSVC.Book oBook)
{
oBook.LanguageID = 1;
_service.AddBooks(oBook.ActualPrice,oBook.ActualPriceString, oBook.Author, oBook.BookId, oBook.BookName, oBook.CategoryID, oBook.Currency, oBook.CurrentPrice, oBook.CurrentPriceString,
oBook.Description, oBook.DiscountPercentage, oBook.DiscountValue, oBook.LanguageID,
oBook.NativeLanguageName, oBook.Publisher);
TempData.Add("SuccessMessage", " New book " + oBook.BookName + " Added !");
return RedirectToAction("Index");
}
Please suggest me.
To correctly bind your model, you need to create the dropdown in the main view. This line in you partial view
#Html.DropDownListFor(m => m.ParentID, ....
will render a select
<select name="ParentID" ...
but you model is expecting a property named CategoryID
In you Create() method, generate the SelectList and assign to a view model property or to ViewBag and then (instead or #Html.Action("GetAllCategory","Books") use
#Html.DropDownListFor(m => m.CategoryID, ....
use this line in your GetAllCategory.cshtml file
#Html.DropDownList("CategoryID", new SelectList(Model.ChildCategories, "ID", "DisplayName"), new { #class = "form-control" })

Resources