I added a field to a view model for a Document that should allow the user to associate it with a Tenant. It works fine if the user does assign a tenant, but if they select the null option from the dropdown, then the validation tells me that "The ItemID field is required.", where ItemID is a field on TenantViewModel.
It occurs to me that perhaps I'm using editor templates wrong - I'm trying to select from a list of tenants, not edit a tenant. If that's wrong, let me know, and maybe suggest a better way to get the dropdown.
namespace TenantPortal.Models
{
public class DocumentViewModel
{
...
[UIHint("SelectTenant")]
public TenantViewModel Tenant { get; set; }
}
public class TenantViewModel
{
private Tenant _ten = null;
public int ItemID { get; set; }
public string Display_Name { get; set; }
public string Legal_Name { get; set; }
...
}
}
Editor Template: SelectTenant.cshtml
#using CMS.DocumentEngine.Types.Tenantportal
#using TenantPortal.Models
#model TenantViewModel
#{
Layout = null;
var opts = new SelectList(TenantProvider.GetTenants(), "ItemID", "Display_Name");
}
#Html.DropDownListFor(model => model.ItemID, opts, "(none)")
If you use data annotations you can add validation to your model.
See my example below:
public class TenantViewModel
{
private Tenant _ten = null;
[Required]
public int ItemID { get; set; }
[Required]
[MaxLength(30)]
public string Display_Name { get; set; }
public string Legal_Name { get; set; }
...
}
For further information about data annotations check this
Also, on your code/controller-action side, you need to use ModelState.IsValid check in order to verify whether your model is valid or not
Your ItemID field is an int so it does not allow null values so the model validation fails. Try changing it to int? (a nullable int). If a value is not set in the form, then the value will be null, but if a value is selected, the ItemID will be the selected value.
I ended up adding another property to my document view model named TenantID, having it communicate with the Tenant property behind-the-scenes, and creating SelectLists for TenantID dropdowns on both Create and Edit views. It's less elegant than I would like, but it works.
Related
I have a Model.
This model requires specific permission to modify each value.
So if I'm not authorized, the field is: #Html.hiddenFor(m => ...)
But the biggest problem is that I can modify this data from the browser console.
public class User
{
[Key] public int Id { get; set; }
[Required] public string Name { get; set; }
[Required] public string Password { get; set; }
}
So I added to the Id field [HiddenInput(DisplayValue = false)] and it's good, but for Password field, User need to "EditUser" claim (it's an example) so I can't use that.
So for now, I use #Html.hiddenFor(m => ...) field, but I can edit value from browser console. And when I submit the form, the value is updated.
It's not really secure.
Any help would be greatly appriciated.
I need to make sure that all View data for a specific Site element is unique, but I want to be able to reuse the value for other Site's with different id's.
Example:
Site One
View one ref: ViewOne
View two ref: ViewOne <-- error
Site Two
View one ref: ViewOne <-- no error since it's a different site
View two ref: ViewTwo
View model:
public class View : AssetsBase, IView
{
public int SiteId { get; set; }
public string Name { get; set; }
public string Ref { get; set; }
public virtual IEnumerable<MetaEntry> MetaEntries { get; set; } = new HashSet<MetaEntry>();
public virtual IEnumerable<HreflangEntry> HreflangEntries { get; set; } = new HashSet<HreflangEntry>();
}
DB Context:
builder.Entity<View>().ToTable("SiteView").HasIndex(sw => sw.Ref).IsUnique();
the current approach works as expected, but I'm limited to only use a Ref value once. is what I want possible?
Thanks to user700390 who provided the solution.
DB Context:
builder.Entity<View>().ToTable("SiteView").HasIndex(sw => new { sw.Ref, sw.SiteId }).IsUnique();
I'm really stumped right now. I've been stuck with this problem for a number of days now and frankly, I'm getting sick and tired of it.
I have this database table: https://gyazo.com/9d1b014ecdba1e244c2f6957b6d9397c
(notice FlightsTable)
My goal is to populate a dropdown menu based on the values from the "Departure" section.
I've tried lots of things and yet I still cannot get to grips with it.
Here's my model:
public class FlightModel
{
public int FlightID { set; get; }
public string Departure { set; get; }
public string Arrival { set; get; }
public int NumberOfSeats { set; get; }
public int NumberOfFlights { set; get; }
}
Controller:
public ActionResult BookFlight()
{
return View();
}
FlightDBEntities (from the FlightsDBModel)
namespace Project_v3.Models
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class FlightsDBEntities : DbContext
{
public FlightsDBEntities()
: base("name=FlightsDBEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<FlightsTable> FlightsTables { get; set; }
}
}
Screenshot of the files: http://gyazo.com/31b447387f349fbbe541f44a358c3096
How do I make the dropdown work in my view for BookFlight? I'm really struggling with this so step-by-step solutions so I can understand every step would be greatly appreciated. Please and thank you.
There are a few ways to do this, this is an example:
You'll need something that actually creates your selectlist:
public SelectList GetAsSelectList()
{
var depts = from f in db.FlightsTables
select new SelectListItem
{
Value = f.Departure,
Text = f.Departure
};
return new SelectList(depts, "Value", "Text");
}
If departures are held in their own table, then it would be better to select them from there, using the Id primary key field as the selectlist's value field
I've assumed that the selectlist will be shown on the same page as FlightModel. If this is the case, then your model needs a property for the selectlist:
public SelectList DepartureList { get; set; }
Your controller method needs to create a FlightModel instance, populate it with whatever you want to show (including the selectlist) and pass it to the View:
public ActionResult BookFlight()
{
var model = new FlightModel
{
DepartureList = GetAsSelectList()
};
return View(model);
}
Depending on what you want the user to do with the selectlist, you display it in the view like this:
#Html.DropDownList("Departure", Model.DepartureList)
In your controller, select the distinct departures
IEnumerable<string> departures = db.FlightsTables.Select(f => f.Departure).Distinct();
and assign to to a ViewBag property (or better, use a view model with a property for the SelectList)
ViewBag.DepartureList = new SelectList(departures);
and in the view (unsure what the property you want to bind to - you have not shown your model for the Booking)
#Html.DropDownListFor(m => m.YourProperty, (SelectList)ViewBag.DepartureList, "-Please select-")
I suspect you may need to modify your flight table. You have a ID column but the have a column for number of flights. Surely you would need information about departure and arrival times for each flight?
Edit
Further to comments, your booking model may look something like.
public class BookingVM
{
public List<FlightModel> FlightList { get; set; } // to display available flights
public string Departure { get; set; } // bind to DepartureList
public int FlightID { get; set; } // bind to FlightID in a dropdown that displays the arrival locations
public int Seats { get; set; } // number of seats booked
public SelectList DepartureList { get; set; } // unique departures
}
You would need to handle the .change() event of the Departure dropdownlist, use ajax to pass the selected departure to a controller method that returns the flightID and arrival locations (and probably the number of available seats for each flight) and use that to populate the second dropdownlist (bound to FlightID and displaying the arrival locations).
Trying to unpack some inherited code and I am new to ASP.NET. My question:
What is available in the controller from a post action in a dropdownlist in C# (ASP.NET MVC5)?
Here is what I have in the view:
#using (Html.BeginForm("SignUp", "Location", FormMethod.Post))
....
#Html.DropDownListFor(
model => model.Member.PillarId, new SelectList (Model.Pillars, "Id", "Title"))
Here is the MemberViewModel:
public class MemberViewModel : IValidatableObject{
public int? LocationId { get; set; }
public int? PillarId { get; set; }
}
Here is the Member model:
public class Member
{
public int Id { get; set; }
public string Name { get; set; }
public int? LocationId { get; set; }
public int? PillarId { get; set; }
public String PillarTitle { get; set; }
Here is the Member model constructor(s):
public Member() { }
public Member(MemberViewModel member)
{
PillarId = member.PillarId;
///
}
Here is the Controller
public ActionResult SignUp(MemberViewModel member){///}
My form is correctly pulling the information from the DB to display, as well as posting correctly to the DB via the Controller. I do not want to change the visual options for the user to choose from (i.e. I think ListBox is out?).
Rather, I want to assign both Member.PillarId as well as the Member.Title based on their choice and have it available in the Controller for non-DB operations.
What is currently available in the SignUp method in the Controller? Can I call Model.Pillars.Title? Is it member.PillarId.Pillars.Id? If not, how can I assign it dynamically based on the user choice?
There are views and modelviews flying around in this code, and I am not sure what is available...
SO has a bunch of answers on the DropDownList, so here's a sampling of articles that are somewhat related to what I am getting at...
* This answer
* ListBox
* ListBoxFor: not MVC dynamic
* SelectList Constructor: Not MVC
With a dropdownlist the only value that will come back is the value of the selected item when posting back.
If you want something else to come back you would need a hidden field on the page and bind a change event listener to the dropdown to set the title in the hidden field
public class MemberViewModel : IValidatableObject{
public int? LocationId { get; set; }
public int? PillarId { get; set; }
public string Title { get; set;}
}
#using (Html.BeginForm("SignUp", "Location", FormMethod.Post))
....
#Html.DropDownListFor(
model => model.Member.PillarId, new SelectList (Model.Pillars, "Id", "Title"))
#Html.HiddenFor(model => model.Title);
javascript
$('#idofdropdown').on('change', function()
{
var selectedTitle = $(this).find(":selected").text();
$('#Title').val(selectedTitle);
});
How to get selected title from a drop down list: Get selected text from a drop-down list (select box) using jQuery
Then in your controller your viewmodel will have the title text inside the Title string :)
Hi I'm struggling to find the correct approach on SO for what I am currently doing, so I thought I would ask.
Here is my simplified code:
The entities are nested types based on using them with EF CodeFirst and the ViewModel is being mapped with AutoMapper.
When posting the form the ModelState is not valid due to the dropdownlist being mapped to model.CourseId and displaying my Course data.. i.e. CourseId = 2, CourseList = Null, but also having the [Required] attribute, really only CourseId is required but I also needed a relevant error message.
I then thought that in my Create GET & POST actions the view should probably just have the CourseId but I still need to display it as a dropdown and populate it and I was unsure as how to do that correctly.
I may also not be understanding how this should be used correctly and if I even need CourseName, i.e. since the Course already exists in the database I just want a foreign key to it, which will still let me show the selected course.
I'm also planning to break out all this mapping and data setting in my controller actions into a separate service layer but at the moment its a small prototype.
// Entities
public class Recipe {
public int Id { get; set; }
public string Name { get; set; }
public Course Course { get; set; }
}
public class Course {
public int Id { get; set; }
public string Name { get; set; }
}
// View Model
public class RecipeCreateViewModel {
// Recipe properties
public int Id { get; set; }
public string Name { get; set; }
// Course properties, as primitives via AutoMapper
public int CourseId { get; set; }
public string CourseName { get; set; }
// For a drop down list of courses
[Required(ErrorMessage = "Please select a Course.")]
public SelectList CourseList { get; set; }
}
// Part of my View
#model EatRateShare.WebUI.ViewModels.RecipeCreateViewModel
...
<div class="editor-label">
Course
</div>
<div class="editor-field">
#* The first param for DropDownListFor will make sure the relevant property is selected *#
#Html.DropDownListFor(model => model.CourseId, Model.CourseList, "Choose...")
#Html.ValidationMessageFor(model => model.CourseId)
</div>
...
// Controller actions
public ActionResult Create() {
// map the Recipe to its View Model
var recipeCreateViewModel = Mapper.Map<Recipe, RecipeCreateViewModel>(new Recipe());
recipeCreateViewModel.CourseList = new SelectList(courseRepository.All, "Id", "Name");
return View(recipeCreateViewModel);
}
[HttpPost]
public ActionResult Create(RecipeCreateViewModel recipe) {
if (ModelState.IsValid) {
var recipeEntity = Mapper.Map<RecipeCreateViewModel, Recipe>(recipe);
recipeRepository.InsertOrUpdate(recipeEntity);
recipeRepository.Save();
return RedirectToAction("Index");
} else {
recipe.CourseList = new SelectList(courseRepository.All, "Id", "Name");
return View(recipe);
}
}
I fixed my particular problem just by doing the below.
[Required(ErrorMessage = "Please select a Course.")]
public int CourseId { get; set; }
// public string CourseName { get; set; }
public SelectList CourseList { get; set; }
The view will use the DropDownListFor helper to map the drop down to my CourseId and that's all I really needed.
On to another problem now with AutoMapper and why it is not mapping back to the Recipe entity in the POST Create action.
I probably first need to find a way to store the relevant Course name in the "CourseName" property.