I have a class marked as follows:
public class MyClass{
[Display(Name="First Name")]
public string FirstName{get;set;}
}
In the Razor view I am accessing it like so, where MyClass is a property on the model:
#Html.Label("MyClass.FirstName")
However the value defined in the Display attribute isn't displayed. If I write:
#Html.LabelFor(model => model.MyClass.FirstName)
This works fine, however for the solution I am working on I have to use the first method. What have I missed on the first method?
UPDATE
Thanks for looking at this question, the problem was caused by the model be altered before the partial view was called. This mean that the model being evaluated against was not the model I was expecting.
The problem is now resolved.
If you are strongly typing your view with the MyClass model try
#Html.LabelFor(model => model.FirstName)
Here is an example from one of my projects.
First the view model class
public class UsersRegisterViewModel
{
[Display(Name = "E-Mail Address")]
[Required(ErrorMessage = "E-Mail address is required")]
[Email(ErrorMessage = "Not a valid e-mail address")]
[Remote("UserNameIsAvailable", "Validation", ErrorMessage = "Username is not available")]
public string UserName { get; set; }
[Display(Name = "Password")]
[Required(ErrorMessage = "Please enter a password")]
public string Password { get; set; }
[Display(Name = "Verify Password")]
[Required(ErrorMessage = "Please confirm your password")]
[Compare("Password", ErrorMessage = "Passwords don't match")]
public string VerifyPassword { get; set; }
[Required(ErrorMessage = "Please enter a display name")]
[Remote("DisplayNameIsAvailable", "Validation", ErrorMessage = "Display name is not avalable")]
public string DisplayName { get; set; }
}
Now the View (Ignore the AJAX goo)
#model UsersRegisterViewModel
<div id="user-register" class="site-contol">
<h2>Account Registration</h2>
<p></p>
#using (Ajax.BeginForm("Register", "Users", null, new AjaxOptions
{
HttpMethod = "post",
UpdateTargetId = "user-registration",
InsertionMode = InsertionMode.Replace,
OnSuccess = "registrationCallBacks.onSuccess",
OnFailure = "registrationCallBacks.onError"
}, new {#id = "frm-sign-in"}))
{
<ul>
<li>#Html.LabelFor(m => m.UserName)</li>
<li>#Html.TextBoxFor(m => m.UserName) #Html.ValidationMessageFor(m => m.UserName)</li>
<li>#Html.LabelFor(m => m.Password)</li>
<li>#Html.PasswordFor(m => m.Password) #Html.ValidationMessageFor(m => m.Password)</li>
<li>#Html.LabelFor(m => m.VerifyPassword)</li>
<li>#Html.PasswordFor(m => m.VerifyPassword) #Html.ValidationMessageFor(m => m.VerifyPassword)</li>
<li>#Html.LabelFor(m => m.DisplayName)</li>
<li>#Html.TextBoxFor(m => m.DisplayName) #Html.ValidationMessageFor(m => m.DisplayName)</li>
<li>
<ul>
<li><input type="submit" name="sb-register" value="Create Account"/></li>
</ul>
</li>
</ul>
}
</div>
Related
I am trying to enter a 'UserId' in the texbox and when I click on 'Find User' button, I need to get 'UserName' and 'Role' from Database based on the UserId and display them in the texboxes so that if Username and Role have to be edited they will be edited and Updated to Database.
But, when I enter UserId, the UserId value is available in the Model, and I am able to query teh database and get the results and assign them to the Model's UserName and Role (Model.UserName and Model.Role), but I am unable bind them to HTML.TextBoxFor.
I have a model like below
public class EditUserInfoModel
{
[Display(Name = "User ID")]
public string UserId { get; set; }
[Display(Name = "User Name")]
public string UserName { get; set; }
[Display(Name = "Role")]
[DataType(DataType.Text)]
public string Role { get; set; }
}
..and Controller like below
[HttpPost]
public ActionResult EditUserInfo(EditUserInfoModel model)
{
if (ModelState.IsValid)
{
string con = ConfigurationManager.ConnectionStrings["DMSCON"].ConnectionString;
DataTable dt = new DataTable();
SqlConnection dbCon = new SqlConnection(con);
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select user_name,user_role from user_info where
user_id=#userid";
cmd.Parameters.Add(new SqlParameter("#userid", model.UserId));
cmd.Connection = dbCon;
dbCon.Open();
SqlDataAdapter dap = new SqlDataAdapter(cmd);
dap.Fill(dt);
EditUserInfoModel myModel = new EditUserInfoModel();
foreach (DataRow row in dt.Rows)
{
myModel.UserName = row["user_name"].ToString();
myModel.Role = row["user_role"].ToString();
//model.isBlocked = (bool)row[""];
//model.isExpired = (bool)row[""];
// model.UserId = "somevalue";
}
return View("EditUserInfo", myModel);
}
return View();
}
and the View like below
#model WebDMS.Models.EditUserInfoModel
#{
ViewBag.Title = "EditUserInfo";
//Layout = "~/Views/Shared/_LayoutPage1.cshtml";
}
<h2>
EditUserInfo</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>EditUserInfoModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.UserId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserId)
#Html.ValidationMessageFor(model => model.UserId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.UserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserName)
#Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Role)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Role)
#Html.ValidationMessageFor(model => model.Role)
</div>
<input type="submit" value="Find User" />
</fieldset>
}
you need to do little modification in your controller action method and view model.
Model
public class EditUserInfoModel
{
[Required]
[Display(Name = "User ID")]
public string UserId { get; set; }
[Required]
[Display(Name = "User Name")]
public string UserName { get; set; }
[Required]
[Display(Name = "Role")]
[DataType(DataType.Text)]
public string Role { get; set; }
}
Controller:
[HttpPost]
public ActionResult EditUserInfo(EditUserInfoModel model)
{
string con = ConfigurationManager.ConnectionStrings["DMSCON"].ConnectionString;
DataTable dt = new DataTable();
SqlConnection dbCon = new SqlConnection(con);
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select user_name,user_role from user_info where
user_id=#userid";
cmd.Parameters.Add(new SqlParameter("#userid", model.UserId));
cmd.Connection = dbCon;
dbCon.Open();
SqlDataAdapter dap = new SqlDataAdapter(cmd);
dap.Fill(dt);
EditUserInfoModel myModel = new EditUserInfoModel();
foreach (DataRow row in dt.Rows)
{
myModel.UserName = row["user_name"].ToString();
myModel.Role = row["user_role"].ToString();
}
//return View("EditUserInfo", myModel); //try removing this line
return View(myModel);
}
If you use dataannotations then you do not need to check ModelState.IsValid in your action method. Your #ValidationMessage on your form fields inside your view will have more meaning then and will work as expected
you do not need to explicitly call the view name. Let the MVC-3 handles that. Instead try it as mentioned in this response.
these are not i would say managed and structured approach though. Always Close() and Dispose() your Db connections by putting them in using() block or try-catch-finally block. Make a layered structure so you can separate your database interaction from your controller actions. Hope it helps.
I need your help. I am working with MVC3-Razor application. I need to validate a textbox on View (.cshtml file) in such a way that, the starting 2 characters must be "PR" and 4th character must be "2". This is the requirement. How would i achieve this functionality? Any suggestions, it would be great help. Thanks for your precious time.
Model
public class RegisterModel
{
public int ID { get; set; }
[RegularExpression(#"^PR[a-zA-Z0-9]2([a-zA-Z0-9]*)$", ErrorMessage = "Please enter valid Name.")]
[Required(ErrorMessage = "Name is required.")]
public string Name { get; set; }
}
View
#using (Html.BeginForm("DYmanicControllerPage", "Test", FormMethod.Post, new { id = "FrmIndex" }))
{
<div>
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
</div>
}
I am having strange issue, MVC dropdown selected value is not preselected on page Load.
My Models are:
public class DocumentTypesViewModel
{
[Required(ErrorMessage = "DocumentType is required")]
public int OHDocumentTypeId { get; set; }
public string OHDocumentTypeDescription { get; set; }
}
public class ClientAdvancedSearchViewModel
{
[Display(Name = "Name")]
public string Name { get; set; }
[Display(Name = "DocumentType")]
public string DocumentTypeId { get; set; }
public IEnumerable<SelectListItem> DocumentTypes { get; set; }
}
In My Controllers I am populating the ClientAdvancedSearchViewModel like this
[HttpGet]
public ActionResult ClientAdvancedSearch()
{
ClientAdvancedSearchViewModel clientAdvancedSearchViewModel = iClientReferralRecordsRepository.GetDocumentMetadata();
//DocumentTypes Dropdown
var ddlDocumentTypes = iDocumentTypeRepository.GetDocumentTypes();
clientAdvancedSearchViewModel.DocumentTypes = new SelectList(ddlDocumentTypes, "OHDocumentTypeId", "OHDocumentTypeDescription",clientAdvancedSearchViewModel.DocumentTypeId);
return View(clientAdvancedSearchViewModel);
}
Finally in the View:
<td>
<div class="editor-label">
#Html.LabelFor(model => model.DocumentTypes)
</div>
<div class="editor-field">
#Html.DropDownListFor(x => x.DocumentTypeId, Model.DocumentTypes, "Please Select", new { #id = "ddlDocumentType" })
</div>
</td>
I believe the Name of the dropdown is same is x => x.DocumentTypeId, becuase of this I think, my value is not preselected.
This is the ViewSource for generated HTML for the Drop Down
<select id="ddlDocumentType" name="DocumentTypeId">
<option value="">Please Select</option>
<option value="20">records</option>
<option value="21"> record1</option>
..
How can I rename my dropdownlist name or How can I solve my problem?
Thank you
Updated: Added the missed line
ClientAdvancedSearchViewModel clientAdvancedSearchViewModel = iClientReferralRecordsRepository.GetDocumentMetadata();
Your code on your view is just right. You forgot to set the value for DocumentTypeId. This is your code as you posted:
[HttpGet]
public ActionResult ClientAdvancedSearch()
{
//DocumentTypes Dropdown
var ddlDocumentTypes = iDocumentTypeRepository.GetDocumentTypes();
clientAdvancedSearchViewModel.DocumentTypes = new SelectList(ddlDocumentTypes, "OHDocumentTypeId", "OHDocumentTypeDescription",clientAdvancedSearchViewModel.DocumentTypeId);
return View(clientAdvancedSearchViewModel);
}
And you missed this:
clientAdvancedSearchViewModel.DocumentTypeId = some_value;
Also, do you intend to have DocumentTypeId as an int instead of a string?
UPDATE:
You can also check that you set the id like this:
#Html.DropDownListFor(x => x.DocumentTypeId, new SelectList(Model.DocumentTypes, "Id", "Value", Model.DocumentTypeId), new { #id = "ddlDocumentType" })
Notice I used the overload with new SelectList. I don't remember all the overloads and I do it like that all the time, so you might check our the other overloads that suits your need.
I want to update Partial View via ajax, but it does not work. Look at this model class:
public class LogOnModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
public bool IsLoggedIn { get; set; }
public string ReturnUrl { get; set; }
}
the following view:
#model ITW2012Mobile.ViewModels.LogOnModel
<div id='LogOn' style="background-color: White;">
#using (Ajax.BeginForm("LogOnAjax", "Home", new AjaxOptions { UpdateTargetId = "LogOn", OnSuccess = "logInComplete" }))
{
ITW2012Mobile.ViewModels.LogOnModel m = Model;
#Html.EditorFor(model => model.IsLoggedIn)
#Html.EditorFor(model => model.ReturnUrl)
<div>
#Html.ValidationSummary()
</div>
<div>
#Html.LabelFor(model => model.UserName)
#Html.EditorFor(model => model.UserName)
</div>
<div>
#Html.LabelFor(model => model.Password)
#Html.EditorFor(model => model.Password)
</div>
<div>
<input type="submit" value="Login" />
</div>
}
</div>
and the following controller class:
public ActionResult LogOnAjax(LogOnModel model)
{
if (!User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
model.IsLoggedIn = true;
model.ReturnUrl = Url.Action("Index", "Home");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return PartialView("PartialViewAjaxLogOn", model);
}
else
{
return PartialView("PartialViewLogOut");
}
}
even when username/password are correct and IsLoggedIn = true and ReturnUrl!=empty view shows empty fields for these variables (but debugger shows values inside). Why and how to make it correctly?
Try clearing the values you are modifying in your action from modelstate or if you use them in html helpers the old values will be used:
ModelState.Remove("IsLoggedIn");
model.IsLoggedIn = true;
ModelState.Remove("ReturnUrl");
model.ReturnUrl = Url.Action("Index", "Home");
Also bear in mind that upon successful authentication and cookie emission you should not display a view (partial in your case). You should redirect so that the authentication cookie is sent by the client on the subsequent request. You should redirect to the return url. But since you are doing this using AJAX you should probably send some indication to the client that the authentication was successful so that you can redirect on the client.
This is very basic but it always returns false on the compare validation. Anyone else running in to this problem?
public class UsersRegisterUserViewModel
{
[DisplayName("E-Mail Address")]
[Required(ErrorMessage = "E-Mail Address is required")]
[RegularExpression(#"^[A-Za-z0-9_\-\.]+#(([A-Za-z0-9\-])+\.)+([A-Za-z\-])+$", ErrorMessage = "Invalid E-mail Address")]
public string RegUsername { get; set; }
[Required]
[Display(Name = "Password")]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required]
[Display(Name = "Confirm Password")]
[Compare("Password", ErrorMessage = "Passwords must match")]
[DataType(DataType.Password)]
public string RegConfirmPassword { get; set; }
}
adapters.add("equalto", ["other"], function (options) {
var prefix = getModelPrefix(options.element.name),
other = options.params.other,
fullOtherName = appendModelPrefix(other, prefix),
//element = $(options.form).find(":input[name=" + fullOtherName + "]")[0];
element = $(options.form).find(":input[name='" + fullOtherName + "']")[0];
MVC3 Compare attribute is buggy when comparing passwords independently of Account Controller. It seems it is hardcoded to only work with Account controller.
1. Cut and past email, password, confirm password from RegisterModel into a new file called ViewModels/ShortRegister.cs
2. Cut razor code ( email, password, confirm password) from register view and past it into partial view, call it "_shortRegistration".
3. Create a new controller called "ShortRegistration". Add the partial view into ShortRegistation.
5. Add related jquery scripts
Create a link on home page to ShortRegistration.
Confirmation error message always fires error message.
Remove the email from the partial view confirmation, The Compare functionality works.
Add userName to the partial view and view-model, Compare functionality fails, again password confirmation error message always displays error message.
Has this bug been fixed? I disabled Compare attribute and wrote jquery and CCS to fix this! I am more than happy to email the code to prove that Compare is buggy.
Hmm, no, I am not running into such problems. I've just tested the following code and it worked perfectly fine as expected.
Model:
public class UsersRegisterUserViewModel
{
[DisplayName("E-Mail Address")]
[Required(ErrorMessage = "E-Mail Address is required")]
[RegularExpression(#"^[A-Za-z0-9_\-\.]+#(([A-Za-z0-9\-])+\.)+([A-Za-z\-])+$", ErrorMessage = "Invalid E-mail Address")]
public string RegUsername { get; set; }
[Required]
[Display(Name = "Password")]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required]
[Display(Name = "Confirm Password")]
[Compare("Password", ErrorMessage = "Passwords must match")]
[DataType(DataType.Password)]
public string RegConfirmPassword { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new UsersRegisterUserViewModel();
return View(model);
}
[HttpPost]
public ActionResult Index(UsersRegisterUserViewModel model)
{
return View(model);
}
}
View:
#model UsersRegisterUserViewModel
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(x => x.RegUsername)
#Html.EditorFor(x => x.RegUsername)
#Html.ValidationMessageFor(x => x.RegUsername)
</div>
<div>
#Html.LabelFor(x => x.Password)
#Html.EditorFor(x => x.Password)
#Html.ValidationMessageFor(x => x.Password)
</div>
<div>
#Html.LabelFor(x => x.RegConfirmPassword)
#Html.EditorFor(x => x.RegConfirmPassword)
#Html.ValidationMessageFor(x => x.RegConfirmPassword)
</div>
<input type="submit" value="OK" />
}
So now the question becomes: how is your code different than mine?