my LogIn is partial view. i pass a model that contain some fields of tbl_profile to partial view and fill it and then i pass filled model to a actionresult in [HttpPost] part and ...
but now i'm trouble in [HttpGet] part . i get this error on this line of cod " *#Html.Action("LogOn","Account")"*.
my code :
[HttpGet]
public ActionResult LogOn(string returnUrl)
{
using (var db = new MyContext())
{
var AllFeatureToLog = db.tbl_profile.Select(u => new UsersClass.LogOn { username = u.username, password_User = u.password_User }).ToList();
return PartialView(AllFeatureToLog);
}
}
class:
public class UsersClass
{
public class LogOn
{
public string username { get; set; }
public string password_User { get; set; }
}
}
LogOn.cshtml:
#model MyProject.Models.UsersClass.LogOn
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<form class="signin-form">
#Html.TextBoxFor(m => m.username, new { #id = "username", #class = "input-block- level", #placeholder = "* enter username" })
#Html.TextBoxFor(m => m.password_User, new { #id = "password", #class = "input-block-level", #placeholder = "* enter pass" })
#Html.ValidationMessage("LoginError")
<label class="checkbox">
<input type="checkbox">remember me</label>
<button class="btn btn-medium btn-general input-block-level" type="submit"> enter</button>
</form>
}
error:
Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'
Use this instead ::
#{ Html.RenderAction("LogOn","Account"); }
This will fix your issue.
You sending List:
var AllFeatureToLog = db.tbl_profile.Select(u => new UsersClass.LogOn { username = u.username, password_User = u.password_User }).ToList();
return PartialView(AllFeatureToLog);
But your View expectiong only one model:
#model MyProject.Models.UsersClass.LogOn
Change: your ActionResult on sending one: var AllFeatureToLog = db.tbl_profile.Select(u => new UsersClass.LogOn { username = u.username, password_User = u.password_User }).Fist();
or View for getting List: #model IENumerable<MyProject.Models.UsersClass.LogOn>
Related
I have a page containing a form and a partial view (containing a form too).
both model have 1 (or more) properties with the same name. when I validate the first form, the value and validation message is duplicate on the second form.
I create a little sample with dummy entities.
person.cs
public partial class Person : IValidatableObject
{
[Required(ErrorMessage = "name required")]
public string Name { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (Name == "admin") //just example
{
results.Add(new ValidationResult("You cant be admin.", new[] { "Title", "Name" }));
}
return results;
}
}
Person/Index.cshtml
#model Person
#{
ViewBag.Title = "Person";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("Index", "Person", FormMethod.Post, new { id = "CreatePersonForm" }))
{
#Html.AntiForgeryToken()
#Html.DisplayNameFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
<input type="submit" value="Save" class="btn btn-default" />
}
#Html.Partial("~/Views/Dog/Index.cshtml", new Dog())
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
PersonController.cs
public class PersonController : Controller
{
// GET: Person
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index([Bind(Include = "Name")] Person person)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
return View(person);
}
}
I made a partial view practically the same.
Dog.cs
public partial class Dog : IValidatableObject
{
[Required(ErrorMessage = "name required")]
public string Name { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (Name == "admin") //just example
{
results.Add(new ValidationResult("You cant be admin.", new[] { "Title", "Name" }));
}
return results;
}
}
Dog/Index.cshtml
#model Dog
#{
ViewBag.Title = "Dog Page";
}
#using (Html.BeginForm("Index", "Dog", FormMethod.Post, new { id = "CreateDogForm" }))
{
#Html.AntiForgeryToken()
#Html.DisplayNameFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
<input type="submit" value="Save" class="btn btn-default" />
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
DogController.cs
public class DogController : Controller
{
// GET: Dog
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index([Bind(Include = "Name")] Dog dog)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
return View(dog);
}
}
if you start /Person/Index, if you write admin in the first textbox (person form), after posting (save) the second form (dog form) have the same text and validation than the first form.
The #Html.EditorFor by default uses the property name as the id and name of the generated HTML, and the validation uses these values to set the error messages! You can pass a value to overwrite that default behavior in your partial view as following:
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger", #data_valmsg_for="partial_name" })
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control", #id="partial_name" } })
So, im currently building an application that needs the user model validating, and if the incorrect properties are filled in to the user it will tell them.
I have the data annotations set up, but im not sure how i relay the error message back to the user?
I have this set up so far on my model and view.
Model
public class DatabaseModel
{
[Required(ErrorMessage = ("A first name is required"))]
public string FirstName { get; set; }
[Required(ErrorMessage = ("A last name is required"))]
public string LastName { get; set; }
[Required(ErrorMessage = ("A valid role is required"))]
public string Role { get; set; }
// TODO - Validate rank to only b 1 - 10
//
[Range(1,10, ErrorMessage = ("A rank between 1 and 10 is required"))]
public int Rank { get; set; }
}
And View
#model RoleCreatorAndEditor.Models.DatabaseModel
#{
ViewData["Title"] = "Index";
}
<h2>User Information</h2>
<p>This is your user information!</p>
#using (Html.BeginForm("Index", "Home", FormMethod.Post)) {
#Html.Label("First Name")
<br>
#Html.TextBoxFor(m => m.FirstName)
<br>
#Html.Label("Last Name")
<br>
#Html.TextBoxFor(m=>m.LastName)
<br>
#Html.Label("Role")
<br>
#Html.TextBoxFor(m => m.Role)
<br>
#Html.Label("Rank")
<br>
#Html.TextBoxFor(m => m.Rank)
<br><br>
<input type="submit" value="Save">
}
My Controller
public class HomeController : Controller
{
// GET: Home
[HttpGet]
public ActionResult Index()
{
DatabaseModel model = new DatabaseModel();
return View(model);
}
[HttpPost]
public ActionResult Index(DatabaseModel model)
{
if (ModelState.IsValid)
{
ListToDatatable convert = new ListToDatatable();
DataTable user = convert.Convert(model);
DatabaseRepository dbRepo = new DatabaseRepository();
dbRepo.Upload(user);
}
return View();
}
}
I believe the model needs to be passed back to the view in order to display the error message, and although i have read through the documentation on asp.net i cannot understand how they just add the error message and the form knows how to display the errors to the user.
I am extremely confused.
You need to use ModelState.IsValid in your Controller and also #Html.ValidationMessageFor(model => model.FirstName) in your view:
public ActionResult Index(ViewModel _Model)
{
// Checking whether the Form posted is valid one.
if(ModelState.IsValid)
{
// your model is valid here.
// perform any actions you need to, like database actions,
// and/or redirecting to other controllers and actions.
}
else
{
// redirect to same action
return View(_Model);
}
}
For your example:
#model RoleCreatorAndEditor.Models.DatabaseModel
#{
ViewData["Title"] = "Index";
}
<h2>User Information</h2>
<p>This is your user information!</p>
#using (Html.BeginForm("Index", "Home", FormMethod.Post)) {
#Html.LabelFor(m=>m.FirstName)
<br>
#Html.TextBoxFor(m => m.FirstName)
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
<br>
#Html.LabelFor(m=>m.LastName)
<br>
#Html.TextBoxFor(m=>m.LastName)
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
. . .
<input type="submit" value="Save">
}
Controller:
[HttpPost]
public ActionResult Index(DatabaseModel model)
{
if (ModelState.IsValid)
{
ListToDatatable convert = new ListToDatatable();
DataTable user = convert.Convert(model);
DatabaseRepository dbRepo = new DatabaseRepository();
dbRepo.Upload(user);
}
return View(model);
}
Using a ViewModel for validation:
public class CCvm
{
[Required(ErrorMessage = "Please enter your Name")]
public string cardHolderName { get; set; }
}
My controller calls a task on post:
public async Task<ActionResult> Pay(FormCollection form, CCvm model)
{
if (!ModelState.IsValid)
{
return View(model);
}
}
And the View:
#model GCwholesale.Models.CCvm
#{
Layout = "~/Views/Shared/_HomeSubPageLayout.cshtml";
ViewBag.Title = "Secure Checkout";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="Payment">
<label>Name on Card: </label>
#Html.EditorFor(model => model.cardHolderName, new { htmlAttributes = new { #placeholder = "Cardholder Name Please", #Value = ViewBag.Name } })<br />
#Html.ValidationMessageFor(model => model.cardHolderName)
<button class="submitCheckout">SUBMIT NOW</button>
</div>
}
But when validation fails the data in the form goes away.
Thanks for taking a look.
You do not need to set #Value = ViewBag.Name inside EditorFor.
#Html.EditorFor(model => model.cardHolderName,
new { htmlAttributes = new { #placeholder = "Cardholder Name Please" } })
Besides, you do not need FormCollection as a parameter because you already have CCvm Model.
public async Task<ActionResult> Pay(CCvm model){
{
//...
}
#Value = ViewBag.Name
You're not setting the ViewBag.Name, so it wouldn't have a value and would result in a blank input. Remove that and let the HtmlHelper set it based off the value in the posted model.
My code is as followed and the error message are not displayed:
Index.cshtml
#model WebApp.Models.OrderItems
#using (Html.BeginForm("SaveToDB", "Home", FormMethod.Post, new { #class = "form-group", role = "form" }))
{
#Html.Partial("Information")
}
Partial : Information.cshtml
#model WebApp.Models.OrderItems
<div class="col-lg-4">
<div class="form-group">
<label for="input1" class="col-lg-4 control-label">#Html.LabelFor(model => model.CLInfo.ClientName)</label>
#Html.EditorFor(model => model.CLInfo.ClientName, new { style = "width:250px" })
#Html.ValidationMessageFor(model => model.CLInfo.ClientName)
</div>
</div>
Model :
public class OrderItems
{
public InfoCLInfo{ get; set; }
}
Model : the class for Infos
public class Info
{
[Display(Name = "Client Name")]
[Required]
public string ClientName{ get; set; }
}
The controller
[HttpPost]
[MultipleButton(Name = "action", Argument = "SaveToDB")]
public ActionResult SaveToDB(OrderItems Client)
{
var errors = ModelState.Values.SelectMany(v => v.Errors);
if (ModelState.IsValid)
{
if (_db == null)
_db = new OrderDB();
OrderItems ClientOrig = Session["Clientobj"] as OrderItems;
ClientOrig.CLInfo = Client.CLInfo;
Session["Clientobj"] = null;
}
return RedirectToAction("Index", "Home");
}
[Authorize]
public ActionResult Index (OrderItems Client)
{
int ClientID = Convert.ToInt32(Session["Client"]);
if ClientID == 0)
{
ClientID = 2;
Session["Client"] = ClientID;
}
if (Session["Clientobj"] == null)
{
Client = new OrderItems();
Client.CLOrderID = 123;
Session["Clientobj"] = Client;
}
else
{
Client = Session["Clientobj"] as OrderItems
}
return View(Client);
}
on post the ModelState.IsValid return false which true, but I don't have any message to tell the user where is the error to be fixed.
I tried to add : #Html.ValidationSummary(true) after the BeginForm , but it didn
Any idea please
Thanks
You cannot use RedirectToAction if you want to retain your model state. All errors and what not are kept in the ModelState object, and when you redirect to action it's performing a new get action, which starts fresh with a clean slate.
You need to return the view like you do in the original action.
I have feedback form on my mvc site, it looks like
I created model for my form
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ComponentTrading.Web.Models
{
public class FeedbackForm
{
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Message { get; set; }
}
}
I created view for my form
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "contact-form" }))
{
<fieldset>
#Html.TextBoxFor(model => model.Name, new { #Value = "Name" })
#Html.TextBoxFor(model => model.Email, new { #Value = "E-mail" })
#Html.TextBoxFor(model => model.Phone, new { #Value = "Phone" })
#Html.TextAreaFor(model => model.Message, new { #class = "img-shadow"})
<input class="form-button" data-type="reset" value="Clear" />
<input class="form-button" data-type="submit" type="submit" value="Send" />
}
and now i try to do a sending a letter to email, but it doesn work, when I push "send-button" it happens nothing and I dont get email
my controller
[HttpGet]
public ActionResult Contacts()
{
FeedbackForm temp = new FeedbackForm();
temp.Message = "Message";
return View(temp);
}
[HttpPost]
public ActionResult Contacts(FeedbackForm Model)
{
string Text = "<html> <head> </head>" +
" <body style= \" font-size:12px; font-family: Arial\">"+
Model.Message+
"</body></html>";
SendEmail("mironny#inbox.ru", Text);
FeedbackForm temp = new FeedbackForm();
return View(temp);
}
public static bool SendEmail(string SentTo, string Text)
{
MailMessage msg = new MailMessage();
msg.From = new MailAddress("Test#mail.ru");
msg.To.Add(SentTo);
msg.Subject = "Password";
msg.Body = Text;
msg.Priority = MailPriority.High;
msg.IsBodyHtml = true;
SmtpClient client = new SmtpClient("smtp.mail.ru", 25);
client.UseDefaultCredentials = false;
client.EnableSsl = false;
client.Credentials = new NetworkCredential("TestLogin", "TestPassword");
client.DeliveryMethod = SmtpDeliveryMethod.Network;
//client.EnableSsl = true;
try
{
client.Send(msg);
}
catch (Exception)
{
return false;
}
return true;
}
what's wrong?
Use
// if you dont pass any parameter
// BeginForm posted to the action that
// has name as view name.
// so no need to write any parameters
#using (Html.BeginForm())
{
...
<input type="submit" value="Send">
}
OR
#using (Html.BeginForm("Contacts", "SomeController", FormMethod.Post, new { id = "contact-form" }))
{
...
<input type="submit" value="Send">
}
You have a few question about mvc and there is more important thing of them is incorrect overload methods. My suggestion, first, you should learn html-helpers overload methods. And MVC model binding strategies...