Problem with getting selected OBJECT from dropdownlist - asp.net

I have a problem with getting selected objectfrom my list.
I bind collection of users to dropdownlist by:
ddlContractors.DataSource = service.GetAllUsers();
ddlContractors.DataTextField = "Name";
ddlContractors.DataValueField = "Id";
ddlContractors.DataBind();
It's working.
But when I try getting selected object by:
var user = (User)ddlContractors.SelectedItem;
I get:
(User)ddlContractors.SelectedItem Cannot convert type 'System.Web.UI.WebControls.ListItem' to 'GWDSite.GWDService.User'
How can I get object user from dropdownlist ? I can change type of my list control if it is necessary

The value field in the dropdown list is the field "Id" not the User object. so 'SelectedItem' is returning the "Id" value -- not the object. You can use that Id to lookup the User object (from session or cache or wherever you can keep it)

You cant.
The SelectedItem is of type ListItem and you cannot just typecast a listItem back into your custom class i.e user.
You can only get the text or the value associated with the item that was selected via SelectedItem / SelectedValue
What you need to do is use that text / value and maybe retrieve your corresponding "User" object based on that text / value from somewhere (depending on how you are doing your state management).

use SelectedValue instead of SelectedItem
WEB APPLICATION
As you are working with web app , approach i was describng will not work here.
you can get the ID of the selected item and use this ID as a parameter to retrive the object from the service layer but if the object is expensive to create than use caching to store your object and retrive it wheb needed.

Related

What is the usage of the copy caller query property in display menu item in D365?

There is a form which is linked to the display menu item. I was checking the property of the menu item and see two properties have yes value, (1) neededRecord and (2) CopyCallerQuery. I discovered that when copyCallerQuery property is true, jumping to this form from other forms failed with this error :
Cannot apply initial query because no form root data source table
matches the query root data source table..
On the other hand, in some situations this form is open by code in a helper class as bellow:
private void openMyForm(MyTable _myTable)
{
MenuFunction _menuFunction;
Args _args;
_args = new Args();
_args.record(_myTable);
_args.caller(this);
_menuFunction = new MenuFunction(menuItemDisplayStr(MyFormDisplayMenu),MenuItemType::Display);
_menuFunction.openMode(OpenMode::Edit);
_menuFunction.run(_args);
}
When I set copyCallerQuery to No the form is open with wrong record but when I set it yes form is open with correct record.
So I want to know what is usage of the CopyCallerQuery property? Did I use it correctly?
copyCallerQuery will specify if the calling form's query should be copied to the target form, for example copying a list page query to a details form.
You can see and better understand this for yourself by
Create a form (Form1)
Add a SalesTable datasource to it
Override an init method at \Forms\Form1\Methods\init and after the super(); call put info(SalesTable_ds.query().toString());
Create a Display menu item (\Menu Items\Display\Form1) with property Object = Form1 and CopyCallerQuery = Yes.
Go to the SalesTable form at \Forms\SalesTable and just add that new menu item (Form1) anywhere on the SalesTable form as a button in the action pane, and set the datasource property to SalesTable
Open the SalesTable form and press the button. Copy the infolog to notepad somewhere.
Modify \Menu Items\Display\Form1 and set CopyCallerQuery = No and then open SalesTable form again and copy the query into notepad and compare the two.
Your error you are receiving is because the caller form's root datasource needs to match the target form's root datasource in order to copy it.

random EntityValidationErrors (The field is required)

I've been trying to update an Entity using the following code:
var db = new MyContext();
var data = db.Tableau.Find(Id);
if (data != null)
{
data.Name = model.Name;
data.EmbedCode = model.EmbedCode;
db.SaveChanges();
}
The problem is that my Tableaus table has a Parent field (FK not null to a DataTree table). Sometimes when I save the changes to this edited record, I get an error saying that "The Parent field is required". But I am not editing the Parent field. The parent field should be intact and existent, since I am only altering the Name and EmbedCode fields.
How to proceed? Thanks in advance.
That is because you are allowing null values in ParentId column in your Tableaus table, but in your Tableau entity you have ParentId as non-nullable property( which it means the relationship is required), and when you load a Tableau instance from your DB, EF expects that you set that property too. Try changing that property to nullable:
public int? ParentId {get;set;}
If you configure your relationship using Fluent Api it would be:
modelBuilder.Entity<Tableau>()
.HasOptional(t=>t.Parent)
.WithMany(dt=>dt.Tablous)// if you don't have a collection nav. property in your DataTree entity, you can call this method without parameter
.HasForeignKey(t=>t.ParentId);
Update 1
If you want ParentId property as Required in your Tableau entity, you need to make sure that you have a valid value in that column in your DB per each row. With a "valid value" I mean it should be different of the default value and it should exist as PK in your DataTree table.
Update 2:
One way to load a related entity as part of your query is using Include extension method:
var data = db.Tableau.Include(t=>t.Parent).FirstOrDefault(t=>t.Id==Id);

change the value of dropdown list after form submition ASP.NET MVC

I have a very strange problem. I want to change selected value of the dropdownlist after form submition. I know that HtmlHelper is retrieving the ModelState value, which is filled with the posted data. But I have a redirect from my POST action to GET action! However my ddl is populated with value submitted during the post. I've also added this code to my post action: ModelState.Clear(), but this hasn't helped me neither.
I've added another ddl to my form just for debugging;
#Html.DropDownList("asd" + Guid.NewGuid(), Model.Voting.Result.ToSelectList())
It always appears with value provided by the server code. But the target ddl
#Html.DropDownListFor(x => x.Voting.Result, Model.Voting.Result.ToSelectList())
always has a value posted by user.
How can I populate the target ddl?
You have to pass the initial value to it like
#Html.DropDownListFor(x => x.Voting.Result,
new SelectList(Model.Voting.Result, "Id", "Name", /*initial value*/))
Use this constructor of SelectList class
Edit
initially I have put the argument on wrong method

how to retrieve the other values in the business entity

The method has a return type of collection<businessEntity>. I am calling the method from the aspx page in order to populate a drop down -> ddlDropDown. I am binding he DataTextField of the ddlDropDown with the BusinessEntity.Name and the DataValueField with BusinessEntity.Id, the business entity contains another id which is BusinessEntity.ProductId. I need to use the ProductId of the value selected in the drop down list in the code behind. Can you help suggest how I can do so?
One possible way could be to call the method in the page_Load on the code behind and save the collection in a hidden variable and when required do a loop through in the hidden variable and retrieve the selected value Product Id.
Your thoughts please.
You could certainly accomplish this using a hidden field.
Here's another idea: bind the DataValueField to a special derived string, containing the BusinessEntity.Id AND the BusinessEntity.ProductId.
In other words, concatenate the BusinessEntity.Id and BusinessEntity.ProductId into a single string, seperated by the pipe ("|") symbol for example.
E.g to bind:
ddlFoo.DataValueField = string.Format("{0}|{1}", "Id", "ProductId");
Then to retrieve selected item:
var id = ddlFoo.SelectedValue.Split("|")[0];
var productId = ddlFoo.SelectedValue.Split("|")[1];
Saves you looping/matching. Again, its not ideal, but then again neither is binding multiple values types to a dropdownlist.

Best way of implementing DropDownList in ASP.NET MVC 2?

I am trying to understand the best way of implementing a DropDownList in ASP.NET MVC 2 using the DropDownListFor helper. This is a multi-part question.
First, what is the best way to pass the list data to the view?
Pass the list in your model with a SelectList property that contains the data
Pass the list in via ViewData
How do I get a blank value in the DropDownList? Should I build it into the SelectList when I am creating it or is there some other means to tell the helper to auto create an empty value?
Lastly, if for some reason there is a server side error and I need to redisplay the screen with the DropDownList, do I need to fetch the list values again to pass into the view model? This data is not maintained between posts (at least not when I pass it via my view model) so I was going to just fetch it again (it's cached). Am I going about this correctly?
Your best bet is to create a SelectList in your Controller - use my extension method here:
http://blog.wekeroad.com/2010/01/20/my-favorite-helpers-for-aspnet-mvc
Pop that into ViewData using the same key as your property name:
ViewData["statusid"]=MySelectList
Then just use Html.DropDownFor(x=>x.StatusID) and you're all set.
Answering in parts:
The best way IMHO is to pass the list in the ViewModel like this:
public SelectList Colors
{
get
{
// Getting a list of Colors from the database for example...
List<Color> colors = GetColors().ToList();
// Returning a SelectList to be used on the View side
return new SelectList(colors, "Value", "Name");
}
}
To get a blank or default option like ( -- Pick a color -- ), you can do this on the view side:
#Html.DropDownListFor(m => m.Color, Model.Colors, "-- Pick a color --")
You'll have to fetch/populate the list again if it's part of the ViewModel.
Take a look at the following blog post. It can give you some tips:
Drop-down Lists and ASP.NET MVC
You could do something like:
<%= Html.DropDownListFor((x => x.ListItems), Model.ListItems, "")%>
or
<%= Html.DropDownList("ListItems", Model.ListItems, "")%>
The last param 'optionLabel' makes a blank list item
In this case, you can see ListItems is a property of the model.
I have made the view strongly typed to the model also.
(You know this already!)
Pass the list in your model with a SelectList property that contains the data
Yes, add it when you build the SelectList. (If you build the list using LINQ, Union might come in handy.)
Yes do do, and yes you are.
I find it more intuitive to work with a sequence of SelectListItems (rather than a SelectList).
For example, this would create an IEnumerable<SelectListItem> from a sequence of customer objects that you can pass to the Html.DropDownListFor(...) helper. The 'Selected' property will optionally set the default item in the dropdown list.
var customers = ... // Get Customers
var items = customers.Select(c => new SelectListItem
{
Selected = (c.Id == selectedCustomerId),
Text = c.Email,
Value = c.Id.ToString()
});

Resources