I'm new to razor mvc and mvc in general. I have an EnumDropDownListFor that displays Countries in the appropriate language. What I need to have is the dropdownlist sorted in alpha order depending on the different localization resx values.
in my cshtml I have:
<div>#Html.LabelFor(m => m.Country)</div>
#Html.EnumDropDownListFor(m => m.Country)
I have an enum CountryModel.cs :
//[Display(Name = "None", ResourceType = typeof(Web.Models.CountryResources.Fixtures))]
//None = 0,
[Display(Name = "Canada", ResourceType = typeof(Web.Models.CountryResources.Fixtures))]
Canada = 1,
[Display(Name = "Mexico", ResourceType = typeof(Web.Models.CountryResources.Fixtures))]
Mexico = 2,
[Display(Name = "UnitedStates", ResourceType = typeof(Web.Models.CountryResources.Fixtures))]
UnitedStates = 3
Values are stored in resx files for the different languages. For English this is displaying in the correct order based on order in countrymodel but for say French, it should be (values coming from country.fr.resx):
Canada
États Unis (which is United States)
Mexique (which is Mexico)
instead of:
Canada
Mexique
États Unis
My list actually has 37 countries and we could add to it at any time. The selected country's integer is written to the db for later retrieval/editing.
So how do I get the EnumDropDownListFor to sort based on resx values? Should I be using something other than the EnumDropdownListFor? I've seen examples for getting values from resx and have that working but I haven't found examples of making it sort appropriately based on those values. Thank you!
Edit: forgot to say my Model has:
[Display(Name = nameof(Account.Account.Country), ResourceType = typeof(Account.Account))]
public CountryModel Country { get; set; }
I ended up switching to a DropDownListFor instead and have it working. Not sure if there is a better way using the EnumDropDownListFor but I couldn't find it.
So, switched from:
#Html.EnumDropDownListFor(m => m.Country)
to:
#Html.DropDownListFor(m => m.Country, EnumHelper.GetSelectList(typeof(Mlc.Acs.Web.Models.CountryModel)).OrderBy(x => x.Text))
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I'm creating a form, and I would like to allow the user to choose their country, and their city. What is the most effective way to do it?
For things like state and country, the possible number is reasonably small enough that you can build dropdowns for this without too much hassle. Here is a plugin for jQuery that has a "country picker" pre-made, and you can easily find the same for State on Google.
When you start talking about cities, there are a vastly large number of them. In my opinion, you're far better off using a simple textbox for this and letting the user fill it in themselves.
EDIT
Here is an example of building a country list from a database in MVC:
Country class (Model)
//This class represents a Country
public class Country
{
public int CountryID { get; set; }
public string CountryName {get; set; }
public Country(int countryID, string countryName)
{
this.CountryID = countryID;
this.CountryName = countryName;
}
}
Controller
List<Country> countries = new List<Country>(); //Create a list of Country objects
IEnumerable<SelectListItem> countryList; //List to hold the values for the dropdownlist
SqlConnection connection = new SqlConnection(connectionString); //build a connection with your connection string
connection.Open();
SqlCommand query = new SqlCommand("SELECT CountryID, CountryName FROM Country", connection); //query the table
query.CommandType = CommandType.Text;
SqlDataReader reader = query.ExecuteReader(); //execute the query
while (reader.Read()) //read out the results, set each result to a Country object
{
Country country = new Country(
Convert.ToInt32(reader["CountryID"]),
reader["CountryName"].ToString());
countries.Add(country); //add to the initial list
}
connection.Close();
//build the list of <SelectListItem>s to pass to the view
countryList = countries.Select(c => new System.Web.Mvc.SelectListItem
{
Text = c.CountryName,
Value = c.CountryID.ToString()
});
ViewBag.CountryList = countryList; //add the list to ViewBag
And the View
#Html.DropDownListFor(x => x.ID, new SelectList(ViewBag.CountryList, "Value", "Text"), new { #class = "formItem" })
This code hits your database for the list of countries and builds a List<Country> from the SqlDataReader. Then we turn these results into a List<SelectListItem> to pass into the view.
The result is a dropdown list that will always contain whatever records are in your database. If you add/remove items, the list will be representative of this.
The #Html.DropDownListFor(x => x.ID) binds the selected Value to the model's ID property, so you simply select this value on POST. (Note that your model will need to contain an ID property for this to work!
EDIT to emphasize the "fun" of making a city selector:
I really, really advise against trying to build a city selector. Check out the list of cities in Kansas (something I picked at random). I didn't bother to count these, but this is a pretty big list, and that alone is one state in one country in the world.
If you went with a database, you'd easily have thousands of records for the United States alone, and that only leaves you with 195 other countries to build data for.
Perhaps you can find a repository that already has this information available, but the amount of work required to make this happen seems prohibitive.
How to get it so i return all of the projections from the below
def c = Company.createCriteria()
def a = c.list(params){
projections{
property 'id', property 'name'
}
}
if(a.size() == 0)
render "404"
else {
render (contentType: 'text/json'){
totalCount = a.totalCount
data = a
}
}
The result comes out like this:
{"totalCount":2,"data":["company1","company2"]}
Where i need it to be:
{"totalCount":2,"data":[{"class":"org.example.Company","id":1,"name":"company1"},{"class":"org.example.Company","id":2,"name":"company2"}]}
In the company domain i have lots of relationships (some one to one, one to many etc...)
my domain looks like the following:
package org.example
import java.sql.Timestamp
class Company {
String name
String abn
String cname
String email
String phone
String position
String address
String city
String postcode
int style
int openbookings;
Date date;
int tokenTotal = 0
int totaltokens
int totalboosts
int totalposts
Timestamp tokenstamp
static hasMany = [users: User, broadcast: Broadcast, bookings: Booking, locations: Location,vimsurvey:VimSurvey,rewards: Reward, tokens: CompanyToken]
static constraints = {
abn nullable: true
date nullable: true
style nullable: true
}
}
Any help would be great:)
????
http://grails.org/doc/1.1/ref/Domain%20Classes/createCriteria.html
See the property section under projections: 'property Returns the given property in the returned results'. I don't really get what you are asking for by 'all the projections'.
Are you simply looking to Find all for your domain? Why are you using a projection?
def a = c.list(params){
projections{
property 'id', property 'name'
}
}
should be
def a = c.list(params){
projections{
property 'id'
property 'name'
}
}
In fact, I get a compilation error when I attempt to do it your way. I still feel like it makes more sense to simply get the entire domain itself unless there is a very specific reason not to.
I have been asked to look at a bug in some ASP.Net MVC code and have a (to me) very odd problem with a SelectList.
The code from the controller to generate the items (a method to return a SelectList, there are 5 in total). Each SelectList is then saved into the ViewData collection.
List<SelectListItem> items = new List<SelectListItem>();
string yesText = "Yes";
string noText = "No";
if (ci.LCID.Equals((int)LanguageCodes.FRANCE))
{
yesText = "Oui";
noText = "Non";
}
SelectListItem yesItem = new SelectListItem();
yesItem.Text = yesText;
yesItem.Value = ((int)MarketingBy.Yes).ToString();
yesItem.Selected = selectedValue != null && selectedValue.Equals(int.Parse(yesItem.Value));
SelectListItem noItem = new SelectListItem();
noItem.Text = noText;
noItem.Value = ((int)MarketingBy.No).ToString();
noItem.Selected = selectedValue != null && selectedValue.Equals(int.Parse(noItem.Value));
items.Add(yesItem);
items.Add(noItem);
return new SelectList(items, "Value", "Text", yesItem.Selected ? yesItem.Value : noItem.Value);
A quick 'quickwatch' at the point of creation suggests everything is ok:
At the point the view is being rendered, the values still look ok. However when the view loads, the first item in the list is always selected. The HTML generated is:
<tr>
<td>Fax</td>
<td>
<select id="MarketingByFax" name="MarketingByFax">
<option value="134300002">Yes</option>
<option value="134300001">No</option>
</select>
</td>
</tr>
(Other values ommitted for clarity).
Any ideas? Or avenues to research? The author is adamant that this was working 'up til last week' (I have no idea either way).
Edit: Code for the view -
<td><%: Html.DropDownList("MarketingByFax", (SelectList)ViewData["MarketingByFaxList"])%></td>
This code looks just horrible in every imaginable aspect (IMHO of course). I have no idea why it doesn't work and I don't want to know. All I can do is to suggest you how to improve it (so you can stop reading this post if you are looking for a solution about why your code doesn't work as I have no freaking idea).
So the first improvement would be to get rid of any ViewData and introduce a view model:
public class MyViewModel
{
public string SelectedValue { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
then I would have a controller action that would populate this view model:
public ActionResult Index()
{
var model = new MyViewModel
{
// I want to preselect the second value
SelectedValue = "No",
Items = new[]
{
new SelectListItem { Value = "Yes", Text = "yeap !" },
new SelectListItem { Value = "No", Text = "nope !" },
}
};
return View(model);
}
and in my strongly typed view I would simply bind the helper to the view model:
<%= Html.DropDownListFor(
x => x.SelectedValue,
new SelectList(Model.Items, "Value", "Text")
) %>
Also if you want to work with some enum types you may find the following extension method useful.
See how easy it is? No more ugly casts with ViewData, no more need to define any lists and specify some complicated conditions, ...
Remark: once again, those are just my 2¢, you can continue the combat with ViewData if you will.
you can try
<%: Html.DropDownList("MarketingByFax", (IEnumerable<SelectListItem>)ViewData["MarketingByFaxList"])%>
dropdwon has an overload that accepts the enumeration of Selectlist type objects and it sets the value of list automatically depending upon Selected property of selectListItems in the list. for this you have to set
ViewData["MarketingByFaxList"] = items;//where item is IEnumerable<SelectListItem> or List<SelectListItem> as you used in your code
PetaPoco has introduced Multi-POCO queries in experimental form (for now). As their blog post suggests and the code it provides this looks nice and all in One-to-One relations when we load multi POCOs per row as long as they don't repeat over the records.
What happens when at least one side is many relation? Actually example code is Many-to-One relational data.
Example code is clearly a Many-to-One relation. I haven't tested any PetaPoco code but what does the provided code on the blog post do? Does every Article have their own User object instance even though some may be the same user or do they share the same user object instance?
And what about other Many relation types? How do they work of they work at all?
Usually I map these one-to-many queries myself like the following example.
[TableName("Blogs"), PrimaryKey("BlogId")]
public class Blog {
public int BlogId {get;set;}
public string Title {get;set;}
[Ignore]
public IList<Post> Posts {get;set;}
}
[TableName("Posts"), PrimaryKey("PostId")]
public class Post {
public int PostId {get;set;}
public int BlogId {get;set;}
public string Subject {get;set;}
public string Content {get;set;}
}
public class FlatBlogPost {
public int BlogId {get;set;}
public string Title {get;set;}
public int PostId {get;set;}
public string Subject {get;set;}
public string Content {get;set;}
}
There are two ways I could display a list of posts for one blog or without too much work, all blogs.
1.Two queries -
var Blog = Db.Query<Blog>(1);
var Posts = Db.Query<Post>("where BlogId = #0", 1);
2.One query =
var flat = Db.Query<FlatBlogPost>("select b.blogid, b.title, p.postid, p.subject,
p.content from blogs b inner join posts p on b.blogid = p.blogid where
b.blogid = #0", 1);
var blog = flat
.GroupBy(x=> new { x.BlogId, x.Title })
.Select(x=> new Blog {
BlogId = x.Key.BlogId,
Title = x.Key.Title,
Posts = x.Select(y=> new Post{
PostId = y.PostId,
BlogId = x.Key.BlogId,
Subject = y.Subject,
Content = y.Content
}).ToList()
});
However usually in number 2 I would map directly from the FlatBlogPost object to my viewmodel for which I need to display the data.
Update
Check out these helpers which extend PetaPoco to support basic One-to-Many and Many-to-One queries. schotime.net/blog/index.php/2011/08/21/petapoco-one-to-many-and-many-to-one/ https://schotime.wordpress.com/2011/08/21/petapoco-one-to-many-and-many-to-one/
My 'One to Many' recipe for Petapoco is below. The docs are not clear enough for me. Create a db connection in Linqpad, it will show you all Navigation properties you can add to generated Petapoco poco classes. Execute the same SQL in Linqpad, to make sure it gets the data you expect.
// subclass the generated Parent table pocos, add navigation prop for children
[ResultColumn] public List<DecoratedChild> Child { get; set; }
// subclass the generated Child table pocos, add navigation prop for parent
[ResultColumn] public DecoratedParent Parent { get; set; }
// to get children with parent info
List<DecoratedChild> children = db.Fetch<DecoratedChild, DecoratedParent>(SELECT child.*, parent.* from ...)
// to get children with parent info, using PetapocoRelationExtensions
List<Child> children = db.FetchManyToOne<Child, Parent>(child => child.ID, "select child.*, parent.* from ...
// to get parents with children info, using PetapocoRelationExtensions
List<Parent> parents = db.FetchOneToMany<Parent, Child>(par => par.ID, child => child.ID != int.MinValue, "select parent.*, child.* from ...
SQL select order important, same as in Fetch types list !!!
navigation props will have parent or children data ...
with 3 levels the call will be like:
List<DecoratedGrandChild> grandChildColl = db.Fetch<DecoratedGrandChild, DecoratedChild, DecoratedParent>(SELECT grandch.* , child.*, parent.* from ...)
Personally I don't think you can avoid another database call to get the comments. You could get a list of all comments for the 10 articles (in the same order the articles are stored) by using an IN clause, and loop through them adding them to each article.comments as you go along and the comment.articleid changes. The only way I can see getting this information in a single sql call would be to use a join but then you'd get duplicate article details for each comment, so maybe this isn't a problem with petapoco, just one of those things that'll never be perfect
I'm trying to figure out the best way to save a simple one-to-many relationship in Linq2Sql.
Lets assume we have the following POCO model (pseduo code btw):
Person has zero to many Vechicles.
class Person
{
IList<Vehicle> Vehicle;
}
class Vehicle
{
string Name;
string Colour;
}
Now, when i save a Person, i pass that poco object to the repository code (which happens to be L2S). I can save the person object fine. I usually do this.
using (Db db = new Db())
{
var newPerson = db.People.SingleOrDefault(p => p.Id == person.Id) ?? new SqlContext.Person();
// Left to right stuff.
newPerson.Name = person.Name;
newPerson.Age = person.Age;
if (newPerson.Id <= 0)
db.People.InsertOnSubmit(newPerson);
db.SubmitChanges();
}
i'm not sure where and how i should handle the list of vehicles the person might have? any suggestions?
using (Db db = new Db())
{
var newPerson = db.People.SingleOrDefault(p => p.Id == person.Id) ?? new SqlContext.Person();
// Left to right stuff.
newPerson.Name = person.Name;
newPerson.Age = person.Age;
// add vehicles.
Vehicle firstV = new Vehicle();
firstV.Name = "some name";
firstV.Person = newPerson; // need to do this to set the person Id on the vehicle.
newPerson.Vehicle.Add(firstV);
// now when you save the Person it should save the Vehicle list
// if you set Cascade save update on the list. (not sure how to do that in L2S
if (newPerson.Id <= 0)
db.People.InsertOnSubmit(newPerson);
db.SubmitChanges();
}
Now you may choose to construct the list of vehicles at another level , with the data that's coming from the interface.
But you need to remember that it's not enough to add the Vehicle to the list on the Person object , you also need to set the vehicles Person property to the person that has the vehicles.
Observation I'm not sure about this but when you do db.People.SingleOrDefault you might be loading the whole People table in memory . That's not something you want to do. Corrected by Slace in the comments.
All you need to do is ensure that there are the appropriate relationships set up within the database.
If your Vehicle table has a PersonId and there is a foreign key between them when you add them to the DBML Linq to SQL will detect that there is a relationship between them and create a Table<T> representation of the relationship.