I initially set up my dropdown with submit button which was fine but now I wanted to have it just work without the button (I added onchange). However now I find another difficulty that initially when page is displayed, if I "select" the first option, nothing happens (obviously) so I though to add "please select" option. I found couple of solutions such as writing my custom list of SelectListOptions but this seems like it could be over the top for my case. Could anyone shed some light here and let me know what would be the easiest option here? Sorry if it is simple answer I am really stuck. Here is my code:
Model
public class SurveyDropdownModel
{
public SelectList selectSurveys { get; set; }
public string selectedId { get; set; }
public IEnumerable<RespondentModel> respondents { get; set; }
public SurveyDropdownModel(List<SurveyModel> surveys)
{
selectSurveys = new SelectList(surveys, "SurveyID", "SurveyTitle");
respondents = null;
}
}
public class SurveyModel
{
[Required]
[Display(Name = "Survey ID")]
public int SurveyID { get; set; }
[Display(Name = "Title")]
public string SurveyTitle { get; set; }
[Display(Name = "Updated")]
public DateTime SurveyUpdatedDate { get; set; }
[Display(Name = "Active")]
bool IsActive { get; set; }
}
Controller
public class HomeController : Controller
{
public ActionResult Index()
{
string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
HealthCheckDataLayer.HealthCheckRepository repo = new HealthCheckRepository(connectionString);
List<SurveyModel> surveyList = repo.ReturnSurveys<SurveyModel>();
var model = new SurveyDropdownModel(surveyList);
return View(model);
}
[HttpPost]
public ActionResult Index(SurveyDropdownModel model)
{
//not important here
}
}
View
#model HealthCheckWebApp.Models.SurveyDropdownModel
#{
ViewBag.Title = "Home Page";
}
<div class="row">
<div class="col-md-4">
<h4>Select product:</h4>
#using (Html.BeginForm("Index", "Home"))
{
#Html.DropDownList("selectedId", Model.selectSurveys, new { onchange = "this.form.submit()" })
}
</div>
</div>
<br />
<br />
#if(Model.respondents!=null)
{
#* not relevant here*#
}
I guess now that I didn't include how do I pull my list , I am calling a stored procedure from my repository there (It's required to do it with SP).
Thanks.
Use #Html.DropDownListFor. Here is a description.
Usage:
#Html.DropDownListFor(x=> x.selectedId, Model.selectSurveys, "Select something", new { onchange = "this.form.submit()" )
Related
I am using autogenerated entity model classes and than i used partial class with metadata to put validations on auto genetrated classes like below.
public class tblDepartmentCustom
{
[Key]
public int DepartmentId { get; set; }
[Required(ErrorMessage = "Department name is required")]
public string DepartmentName { get; set; }
}
[MetadataType(typeof(tblDepartmentCustom))]
public partial class tblDepartmentMaster
{
}
The original class that was generated by entity framework is given below.
public partial class tblDepartmentMaster
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public tblDepartmentMaster()
{
this.tblDesignationMasters = new HashSet<tblDesignationMaster>();
}
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<tblDesignationMaster> tblDesignationMasters { get; set; }
}
So the problem here is that whenever i try to validated model state it comes out to be true.below is the code.
#model EmployeeManager.Models.tblDepartmentCustom
#{
ViewBag.Title = "InsertDepartment";
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}<div class="col-md-4">
#using (Html.BeginForm("InsertDepartment", "Departments", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<span class="error-class">#ViewBag.FoundError</span>
<br />
<label>Department Name</label>
#Html.TextBoxFor(m => m.DepartmentName, new { #class = "form-control" })
<br />
<input type="submit" class="btn btn-info" value="Add Department" />
}
</div>
And the action below.
[HttpGet]
public ActionResult InsertDepartment()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
[ActionName("InsertDepartment")]
public ActionResult InsertDepartmentPost()
{
using (PMSEntities dc = new PMSEntities())
{
tblDepartmentMaster dm = new tblDepartmentMaster();
TryUpdateModel(dm);
if(ModelState.IsValid)
{
dc.tblDepartmentMasters.Add(dm);
dc.SaveChanges();
return View("_Success");
}
else
{
ViewBag.FoundError = "Department name is required.";
return View();
}
}
}
In order for partial classes to work, both partials must have the same namespace. You don't have to move the actual files around your file structure, just edit the namespace of tblDepartmentCustom to match that of tblDepartmentMaster.
Im tryin to ceate a very simple blog. In my view i got this:
#using (Html.BeginForm("AddBlogPost", "Home")) <--Probably missing something here
{
foreach (var item in Model.BlogPost)
{
#Html.LabelFor(x=>item.Title)
#Html.TextBoxFor(x=>item.Title)
#Html.LabelFor(x=>item.Text)
#Html.TextBoxFor(x=>item.Text)
}
<input type="submit" value="Create Post" />
}
With the submit-button, im hoping to pass the two values to this controller:
public ActionResult AddBlogPost(BlogPost model)
{
BlogPost post = new BlogPost()
{
Title = model.Title,
Text = model.Text,
};
RavenSession.Store(post);
RavenSession.SaveChanges();
return RedirectToAction("Index");
}
Creating a new blogpost and saving it to the DB.
The problem is that the method receives null. Guess im missing somehting silly?
EDIT:
Im not longer passing a list of blogposts...:
#using (Html.BeginForm("AddBlogPost", "Home"))
{
#Html.LabelFor(Model.Title)
#Html.TextBoxFor(Model.Title)
#Html.LabelFor(Model.Text)
#Html.TextBoxFor(Model.Text)
<input type="submit" value="Create Post" />
}
This does not seem to be the right way...
EDIT 2: These are my two class:
public class ContentPage
{
public ContentPage()
{
Template = new RouteTemplate();
ParentReference = "";
Url = "/";
}
public string ParentReference { get; set; }
public RouteTemplate Template { get; set; }
public string Url { get; set; }
public bool ShowInMenu { get; set; }
public string Title { get; set; }
public string Id { get; set; }
public BlogPost BlogPost { get; set; }
}
Blog-class:
public class BlogPost
{
public string Title { get; set; }
public string Text { get; set; }
}
To the view I pass the COntentPage, which contains an instance of the Blog-post...I cant seem to access the blogpost in the way you are describing? Sorry for not being vlear from the start.
Bind you View with the BlogPost class and don't use foreach loop. See the following code.
#using (Html.BeginForm("AddBlogPost", "Home"))
{
#Html.LabelFor(x=>Model.Title)
#Html.TextBoxFor(x=>Model.Title)
#Html.LabelFor(x=>Model.Text)
#Html.TextBoxFor(x=>Model.Text)
<input type="submit" value="Create Post" />
}
i have a page that contains 3 partial views.
...
.
.
#Html.Action("one" , "Home")
#Html.Action("two" , "Home")
#Html.Action("three" , "Home")
.
.
.
i have 5 table in data base.and some of them have relation.some fields of these table should be filled in partial ONE,some should be filled in partial TWO,and ...
i make a class of combination this 5 table.
public class ViewModelX
{
public Nullable<long> id_sport { get; set; }
public Nullable<long> id_city { get; set; }
public Nullable<long> id_spend { get; set; }
public Nullable<long> id_profile { get; set; }
public Nullable<int> cost { get; set; }
public Nullable<long> idFactor { get; set; }
public Nullable<long> Idpage { get; set; }
public string username { get; set; }
public string Namestar { get; set; }
public string Lnamestar { get; set; }
public string Tell { get; set; }
public string cell { get; set; }
public string Address { get; set; }
public string Code { get; set; }
public string username_s { get; set; }
public Nullable<long> id_s { get; set; }
public Nullable<long> id_mark{ get; set; }
}
now i should pass this model to every partial?
and i should pass it to my basic page that contains this 3 partial views too?
You should not Pass the Model(associated with your Business Layer) to you View.
Your opinion might comes simply from a desire to write/maintain less code. So, It is obvious why creating new view models all of the
time will lead to more code.
Reasons to Use a View Model when it makes sense (and this has happened to me), this allows you to validate your view model
differently than your model for attribute-based validation scenarios.
View model objects can be used to help shape and format data. Need a date or money value formatted a particular way? You can do that in
the view, in the controller, or in the view model. If all you are
doing is formatting and such, you can make a case that the view model
is the best place to do it.
By using a view model you have a good mechanism to flatten out and simplify what the view deals with. This will also filter down what can
be seen in intellisense, so if you have different people developing
the models than those working on the views, creating a simple view
model can make it much easier for those just dealing with the UI.
Conslusion : View Model should contain only those properties that are required for it's corresponding View.
Reference
View Models
public class PartialViewModel1
{
[Display(Name = "Name")]
public String Name { get; set; }
}
public class PartialViewModel2
{
[Display(Name = "id")]
public int id { get; set; }
}
public class PartialViewModel3
{
[Display(Name = "DOB")]
public DateTime DOB { get; set; }
}
Controller Action Methods
[HttpGet]
public PartialViewResult PartialView1()
{
return PartialView(new PartialViewModel1());
}
[HttpGet]
public PartialViewResult PartialView2()
{
return PartialView(new PartialViewModel2());
}
[HttpGet]
public PartialViewResult PartialView3()
{
return PartialView(new PartialViewModel3());
}
Partial Views - 1
#model Practise.Controllers.PartialViewModel1
#using (Html.BeginForm("Action", "Controller", FormMethod.Post))
{
#Html.EditorForModel();
<input type="submit" name="Submit" value="Submit" />
}
Partial Views - 2
#model Practise.Controllers.PartialViewModel2
#using (Html.BeginForm("Action", "Controller", FormMethod.Post))
{
#Html.EditorForModel();
<input type="submit" name="Submit" value="Submit" />
}
Partial Views - 3
#model Practise.Controllers.PartialViewModel3
#using (Html.BeginForm("Action", "Controller", FormMethod.Post))
{
#Html.EditorForModel();
<input type="submit" name="Submit" value="Submit" />
}
View
#Html.Action("PartialView1", "Account", new { area = "AreaName" })
#Html.Action("PartialView2", "Account", new { area = "AreaName" })
#Html.Action("PartialView3", "Account", new { area = "AreaName" })
I had your problem before .
If your partial view should get some data use #Html.RenderAction() like below:
Your Partial view (_theLastPost.cshtml) :
#model IEnumerable<test1.Models.Post>
#foreach (var item in Model)
{
<h2>
#item.Title
</h2>
<p>
#item.Content
</p>
}
In your Index.cshtml embed partial view :
#{ Html.RenderAction("_theLastPost"); }
And you should have a controller with same name of partial view like below :
public PartialViewResult _theLastPost()
{
var a = (from c in db.Posts
orderby c.ID_Post descending
select c);
return PartialView(a.ToList());
}
Based on this post
Second answerI tried to create a dropdown list for my register page.
Register page has a field where you can select the PossibleAccessRight for the user while registering him/her which should be saves in AccessRight Attribute.
Right now i can't even show the items in dropdownlist
My model looks like this
public class UserModel
{
public int UserId { get; set; }
[Required]
[EmailAddress]
[StringLength(100)]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email ID ")]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[StringLength(20,MinimumLength = 6)]
[Display(Name = "Password ")]
public string Password { get; set; }
[Required]
[Display(Name = "First Name ")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name ")]
public string LastName { get; set; }
[Required]
[Display(Name = "Address ")]
public string Address { get; set; }
public List<string> PossibleRights;
[Required]
[Display(Name = "Access Rights")]
public string AccessRight { get; set; }
public UserModel()
{
PossibleRights = new List<string>()
{
{"High"},
{"Low"},
};
}
}
in controller i have this in registeration method which is httppost method
[HttpGet]
public ActionResult Register()
{
return View();
}
[HttpPost]
public ActionResult Register(Models.UserModel user)
{
var rights = new UserModel();
if (ModelState.IsValid)
{
using (var db = new DBaseEntities())
{
var crypto = new SimpleCrypto.PBKDF2();
var encrpPass = crypto.Compute(user.Password);
var sysUser = db.SystemUsers.Create();
sysUser.FirstName = user.FirstName;
sysUser.Email = user.Email;
sysUser.Password = encrpPass;
sysUser.PasswordSalt = crypto.Salt;
db.SystemUsers.Add(sysUser);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("","Login data is incorrect.");
}
return View(rights);
}
View for this method looks like this
<div class="editor-label">#Html.LabelFor(u=> u.FirstName)</div>
<div class="editor-field"> #Html.TextBoxFor(u=> u.FirstName)</div>
<br/>
<div class="editor-label">#Html.LabelFor(u=> u.LastName)</div>
<div class="editor-field"> #Html.TextBoxFor(u=> u.LastName)</div>
<br/>
<div class="editor-label">#Html.LabelFor(u=> u.Address)</div>
<div class="editor-field"> #Html.TextBoxFor(u=> u.Address)</div>
<br/>
<div class="editor-label">#Html.LabelFor(u=> u.Email)</div>
<div class="editor-field"> #Html.TextBoxFor(u=> u.Email)</div>
<br/>
<div class="editor-label">#Html.LabelFor(u=> u.Password)</div>
<div class="editor-field"> #Html.PasswordFor(u=> u.Password)</div>
<br/>
<div class="editor-label">#Html.LabelFor(u=> u.AccessRight)</div>
<div class="editor-field"> #Html.DropDownListFor(u=> u.PossibleRights, new SelectList(Model.PossibleRights))</div>//error at this line(NullReference exception)
<br/>
<input type="submit" value="Register"/>
any idea what I'm doing wrong? Also, is my approach to show the items in dropdownlist good? Can you suggest better idea if any?
If you want to display any info on the view, you have to provide this info to the view first. Right now this code:
public ActionResult Register()
{
return View();
}
does not provide any info at all. Model for the view is created with default constructor, which means that model object is empty, therefore nothing is displayed on the view (particularly in the dropdown list). What you need is some initialization like this:
public ActionResult Register()
{
UserModel model = new UserModel();
model.PossibleRights = new List<string>{"Right1", "Right2", "Right3"};
// or go to db, or whatever
return View(model);
}
Besides dropdown returns selected value when posted, which is string representing a right in this case. So you need to introduce some field in the model to store the selection:
public class UserModel
{
...
public List<string> PossibleRights;
public string SelectedRight;
...
}
Usage on view is the following:
#Html.DropDownListFor(u => u.SelectedRight, new SelectList(Model.PossibleRights))
I create a website for my wife. She's a teacher and she would like to have a possibility to create exercises for their students. The case is that she would like to create for instance the following exercise:
Exercise 1: Fill the sentence using a correct word:
My wife is 30 ............. old
I live in this city for 30 .........
I have the following model:
public class Exercise
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ExerciseType Type { get; set; }
public DifficulityLevel DifficulityLevel { get; set; }
public List<ExerciseItem> Items { get; set; }
public DateTime TimeOfCreation { get; set; }
public DateTime TimeOfModification { get; set; }
}
public class ExerciseItem
{
[Key]
public Guid Id { get; set; }
public string Content { get; set; }
public List<ExerciseItemOption> Options { get; set; }
public ExerciseItemOption CorrectSelection { get; set; }
}
I creates a View for my Exercise. I can fill in the basic properties like Name, Description, Difficulity Level and Type. Then I would like to create a button "Add exercise item". When clicked, a partial view (or something else) should be added dynamically where new ExerciseItem can be provided.
I've tried to following:
I've added a button
#Ajax.ActionLink("Add exercise item",
"AddExerciseItem",
"Exercise", new AjaxOptions() { HttpMethod="GET", InsertionMode = InsertionMode.InsertBefore, UpdateTargetId="ExerciseItems"})
and the appropriate div:
<div id="ExerciseItems"></div>
My action method looks as follows:
public ActionResult AddExerciseItem()
{
return PartialView("ExerciseItem", new ExerciseItem());
}
and the partial view:
#model ElangWeb.Models.ExerciseItem
<fieldset>
<legend>ExerciseItem</legend>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.DisplayNameFor(model => model.Content)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Content, new { style = "width:200px" })
</div>
</fieldset>
It works fine. However when I click button for creating a whole exercise, I do not have ExerciseItem collection in my model:
public ActionResult Create(Exercise exercise)
{
using (PersistanceManager pm = new PersistanceManager())
{
exercise.Id = Guid.NewGuid();
exercise.TimeOfCreation = DateTime.Now;
exercise.TimeOfModification = DateTime.Now;
pm.ExcerciseRepository.Add(exercise);
}
return RedirectToAction("Index");
}
How should I change the code in order to bind my list of added ExerciseItem objects to my model Exercise?
Check out this article about model binding. You basically need to create special names for the exercise items so that they get bound correctly.
e.g. partial:
#model ElangWeb.Models.ExerciseItem
<fieldset>
<legend>ExerciseItem</legend>
<label>content</label>
<input type="hidden" name="ExcersiseItem.Index" value="SomeUniqueValueForThisItem" />
<input type="text" name="ExcersiseItem[SomeUniqueValueForThisItem].Name" value="#Model.Content" />
</fieldset>
You can also look at my answer to this question MVC3 Non-Sequential Indices and DefaultModelBinder. Thanks Yarx for finding it, I was actually trying to find it :)