Strange error after getting Value from Html.DropDownList - c#

I crated SelectList selectList with data from my Entities.
And now I want send value from DropDownList to Entitie.
everything is OK (I got value from selected item) , but I got his error et the end
An exception of type 'System.InvalidOperationException' occurred in System.Web.Mvc.dll but was not handled in user code
Additional information: There is no ViewData item of type 'IEnumerable' that has the key 'Przelew.DaneKont'.
#Html.DropDownList("Przelew.DaneKont", ViewBag.DaneKontList as SelectList, "-- Wybierz kontot --")
Viewmodel:
#Html.DropDownList("Przelew.DaneKont", ViewBag.DaneKontList as SelectList, "-- Wybierz kontot --")
Controller:
[Authorize]
[HttpGet]
public ActionResult WykonajPrzelew( ) {
using (var context = new BankAppEntities1())
{
konto = context.Konto.SqlQuery("SELECT * FROM dbo.Konto WHERE UserId = '" + userIdValue + "' ").ToList();
}
WykonajPrzelewMultipleView mymodel = new WykonajPrzelewMultipleView();
mymodel.Konta = konto;
List<SelectListItem> items = new List<SelectListItem>();
foreach (var item in konto){
items.Add(new SelectListItem { Text = item.Nazwa+ " Saldo :"+item.Saldo , Value = item.KontoId+"" });
}
ViewBag.DaneKont = items;
SelectList selectList = new SelectList(items, "Value", "Text");
ViewBag.DaneKontList = selectList;
return View(mymodel);
}
[Authorize]
[HttpPost]
public ActionResult WykonajPrzelew(WykonajPrzelewMultipleView model)
{
string imie = model.Przelew.ImieOdbiorcy;
string nazwisko = model.Przelew.NazwiskoOdbiorcy;
int numerOdbiorcy = Convert.ToInt32(model.Przelew.NumerRachunkuOdbiorcy);
int kontoID = Convert.ToInt32(model.Przelew.DaneKont); // I got Value from List
string tytul = model.Przelew.Tytuł;
string ulica = model.Przelew.Ulica;
string numerdomu = model.Przelew.nrdomu;
string kod = model.Przelew.Kodpocztowy;
string miasto = model.Przelew.Miasto;
string tyt =model.Przelew.Tytuł;
decimal kwota = model.Przelew.Kwota;
DateTime date = System.DateTime.Now;
using (var context2 = new BankAppEntities1())
{
var dane = new Przelew { Imie = imie, Nazwisko = nazwisko, NumerKontaOdbiorcy = numerOdbiorcy, KontoId = "1", NumerKontaNadawcy = 3444666, Ulica = ulica, Nr_domu = numerdomu,Kod_pocztowy="343", Miasto = miasto, Typ = "Normlany", UserId = userIdValue,Kwota=kwota , Date=date , Tytul=tyt };
context2.Przelew.Add(dane);
context2.SaveChanges();
}
return View();
}

You need another property on your model such as DaneKont, and change your view to the following:
#Html.DropDownList("DaneKont", (SelectList)ViewBag.DaneKontList, "-- Wybierz kontot --")
On postback, DaneKont will hold the selected value.

Related

Making a default in a DropDownListFor when displaying from a model

How can I make a blank default to be displayed like " " in this #Html.DropDownListFor.
I have tried the over-rides and they don't work for this.
HTML:
<td>#Html.DropDownListFor(o => o.TerminalsDDL, Model.TerminalsDDL, new { id = "ddlTerminalID", #class = "form-control align-middle" })</td>
Controller:
public ActionResult Index()
{
var model = TCBL.GetTerminalData();
return View(model);
}
//POST: TerminalCommand/Index
/*This function will insert a user selecter terminal command into the TerminalCommand table*/
public ActionResult AddTerminalCommand(AddTerminalCommandVM input)
{
TerminalCommand terminalCommand = new TerminalCommand();
terminalCommand.TerminalID = input.TerminalID;
terminalCommand.Command = input.CommandID;
terminalCommand.CommandValue = input.CommandValue;
TCBL.AddTerminalCommand(terminalCommand);
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index", "TerminalCommand");
return Json(new { Url = redirectUrl });
}
Data Layer:
/*Gets All termianls for the terminalsDDL and all terminal Cmds for Model.TerminalCommands*/
public TerminalCommandVM GetTerminalData()
{
TerminalCommandVM terminals = new TerminalCommandVM();
//For Terminal drop downs
terminals.TerminalsDDL = TCDA.GetTerminalsDropDown();
//For terminal cmd lists
terminals.TerminalCommands = TCDA.GetAll();
//For helpdescription
terminals.HelpDescriptions = TCDA.GetAllHelpDescriptionValues();
terminals.HelpDescriptionID = TCDA.GetAllHelpDescriptionIDs();
//For TerminalCommandLookupsDDL
List<SelectListItem> terminalCommandLookups = new List<SelectListItem>();
var terminalCommandLookupsResults = TCDA.GetAllTerminalCommandLookups().OrderBy(o => o.Name); //.Where(x => x.Name.Contains("S3"));
if (terminalCommandLookupsResults != null)
{
foreach (var item in terminalCommandLookupsResults)
{
SelectListItem newItem = new SelectListItem();
newItem.Text = item.Name;
newItem.Value = item.ID.ToString();
terminalCommandLookups.Add(newItem);
}
}
var terminalCommandValues = TCDA.GetAllTerminalCommandValues();
terminals.TerminalCommandValues = terminalCommandValues;
terminals.TerminalCommandLookupsDDL = terminalCommandLookups;
return terminals;
}
Bottom is data access layer, where the CA gets the data for display. I believe HTML should have some sort of default blank selection though..
You can add a blank default before the for loop in your Data Layer
SelectListItem newItem = new SelectListItem();
newItem.Text = "";
newItem.Value = "";
terminalCommandLookups.Add(newItem);
you can use this overload of Dropdownlistfor -
Html.DropDownListFor(Expression<Func<dynamic,TProperty>> expression, IEnumerable<SelectLestItem> selectList, string optionLabel, object htmlAttributes)
like this
<td>#Html.DropDownListFor(o => o.TerminalsDDL, Model.TerminalsDDL,"", new { id = "ddlTerminalID", #class = "form-control align-middle" })</td>

View List from controller to View

I am just trying out stuff, I have items from different models and want to return them to as one(if its possible).
I have this ActionResult which returns all products from my database:
[HttpGet]
public ActionResult GetAllContents()
{
ViewData["listy"] = GetColors();
var i = (from p in db.tProducts
select p).ToList();
return View(i);
}
and the list is coming from this method
public List<SelectListItem> GetColors()
{
var listy = new List<SelectListItem>();
var colorList = from a in db.tColors
select new SelectListItem
{
Text = a.id.ToString(),
Value = a.name
};
foreach (var item in colorList)
listy.Add(item);
return listy;
}
So how do I display this list as a dropdown on the View?
you can use as below
#Html.DropDownList("listy", ViewData["listy"] as List<SelectListItem>)
You need to parse your object to list of SelectListItem, you can use the following
#Html.DropDownListFor(m => m.Colors, ViewData["listy"] as List<SelectListItem>, "-Colors-", new { })

Populate a view model with a data model with a method aswell

i need to populate my articles ViewModel with a model that has the database data in it, but i have a method that i need to assign to one of my properties
The list of images is the property that needs the method on it.
The method is called once for every item in the list of articles.
Here is my code:
public ActionResult ArticleTypes(string at)
{
articleViewModel.Images = new List<ImageInfo>();
var query = (from a in db.Articles
where a.SelectedArticleType == at
select new ArticlesViewModel
{
Id = a.Id,
Body = a.Body,
Headline = a.Headline,
PostedDate = a.PostedDate,
SelectedArticleType = a.SelectedArticleType,
UserName = a.UserName,
}).ToList();
articleViewModel.Images = imageService.GetImagesForArticle(articlemodel.Id.ToString());
return View(query);
}
I have also tried putting the method inside the linq:
public ActionResult ArticleTypes(string at)
{
articleViewModel.Images = new List<ImageInfo>();
var query = (from a in db.Articles
where a.SelectedArticleType == at
select new ArticlesViewModel
{
Id = a.Id,
Body = a.Body,
Headline = a.Headline,
PostedDate = a.PostedDate,
SelectedArticleType = a.SelectedArticleType,
UserName = a.UserName,
Images = imageService.GetImagesForArticle(a.Id.ToString())
}).ToList();
return View(query);
}
it throws an exception of:
An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: LINQ to Entities does not recognize the method 'System.Collections.Generic.List`1[New_MinecraftNews_Webiste_MVC.Models.ImageInfo] GetImagesForArticle
I added a foreach loop at the end insted of anything else and it works:
public ActionResult ArticleTypes(string at)
{
articleViewModel.Images = new List<ImageInfo>();
var modelList = (from a in db.Articles
where a.SelectedArticleType == at
select new ArticlesViewModel
{
Id = a.Id,
Body = a.Body,
Headline = a.Headline,
PostedDate = a.PostedDate,
SelectedArticleType = a.SelectedArticleType,
UserName = a.UserName
}).ToList();
foreach (var model in modelList)
{
model.Images = imageService.GetImagesForArticle(model.Id.ToString());
}
return View(modelList);
}

C# passing boolean value as message

I have a ViewModel with "HasBeenShipped" which is a boolean, how in my controller would I send it to the view as;
If (hasbeenshipped = false)
my message i want to send to the view
else
Order has been shipped
And in the view how would I display one of these?
Possibly with a viewbag i thought?
Here is my controller
public ActionResult Index()
{
string currentUser = this.User.Identity.GetUserName();
List<T_shirt_Company_v3.ViewModels.MyOrdersViewModel> list = (from o in new TshirtStoreDB().Orders
.Where(o => o.Username == currentUser)
.OrderBy(o => o.OrderDate)
.Select(o => new MyOrdersViewModel()
{
OrderId = o.OrderId,
Address = o.Address,
FirstName = o.FirstName,
LastName = o.LastName,
City = o.City,
OrderDate = o.OrderDate,
PostalCode = o.PostalCode,
Total = o.Total,
HasBeenShipped = o.HasBeenShipped,
Details = (from d in o.OrderDetails
select new MyOrderDetails
{
Colour = d.Product.Colour,
Quantity = d.Quantity,
Title = d.Product.Title,
UnitPrice = d.UnitPrice
}).ToList()
}).ToList()select o).ToList();
//ViewBag.ShippedMessage = HasBeenShipped ? "blah" : "not shipped";
return View(list);
Because the ViewModel contains HasBeenShipped this should work:
View.cshtml
#model List<T_shirt_Company_v3.ViewModels.MyOrdersViewModel>
#foreach (var item in Model)
{
<span>#(item.HasBeenShipped ? "..." : "...")</span>
}
No need to use ViewBag, or perhaps only if the messages themselves have to be loaded from an outside source, which should then be done in the Controller.
In your controller use ViewBag. Such as
ViewBag.ShippedMessage = list.Where(w=>w.HasBeenShipped).Any() ? "blah" : "not shipped";
Then in your view you can access that property
<p>#ViewBag.ShippedMessage</p>

Having a certain ID in the drop down list always at the bottom

I have a subject dropdownlist for a contact form. I always want the Other to be at the bottom of the list. The reason I ask this is because I created a controller so if I wanted to add more subjects I could do so. Anyways suggestions or ways I could go about making sure that the position of the Other subject is always on the bottom of the list?
public void PrepareSubjectCombo()
{
// Grab a list of subjects for the dialog box
IRepository<Subject> subjectRepository = new Repository<Subject>();
List<Subject> subjects = subjectRepository.GetAll().OrderBy(t => t.Position).ToList();
subjects.Insert(0, new Subject() { ID = 0, Name = "- Please Select -" });
ViewData["Subjects"] = subjects;
}
I have posted my combo box if this is of any help
You should simply use the proper overload of the DropDownList helper when rendering your dropdown in the view instead of trying to insert some dummy items into the collection:
public void PrepareSubjectCombo()
{
// Grab a list of subjects for the dialog box
IRepository<Subject> subjectRepository = new Repository<Subject>();
List<Subject> subjects = subjectRepository.GetAll().OrderBy(t => t.Position).ToList();
ViewData["Subjects"] = subjects;
}
and then in the view:
#Html.DropDownList(
"selectedSubject",
new SelectList(ViewData["Subjects"] as List<Subject>, "ID", "Name"),
"- Please Select -"
)
Now this being said, everytime I see someone using ViewData/ViewBag/ViewCrap instead of strongly typed views and view models I get sick and I feel myself into the obligation to show the correct way of doing this.
As always you start with a view model:
public class MyViewModel
{
public string SelectedSubject { get; set; }
public IEnumerable<SelectListItem> Subjects { get; set; }
}
then you have a controller action which will take care of populating this view model:
public ActionResult Index()
{
// TODO: You definitively don't want to hardcode your repository like this
// but use a constructor injection or this action will be impossible to unit test
IRepository<Subject> subjectRepository = new Repository<Subject>();
var subjects = subjectRepository.GetAll().OrderBy(t => t.Position).ToList();
var model = new MyViewModel
{
Subjects = subjects.Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Name
})
};
return View(model);
}
and finally in your strongly typed view:
#model MyViewModel
#Html.DropDownListFor(
x => x.SelectedSubject,
new SelectList(Model.Subjects, "Value", "Text"),
"- Please Select -"
)
DropDownList1.DataSource = YourDataSource;
DropDownList1.DataBind();
//Insert Other subject to the end
ListItem litem = new ListItem(" Other subject ", "value");
DropDownList1.Items.Insert(DropDownList1.Items.Count, litem);
Modify your code as shown below:
public void PrepareSubjectCombo()
{
// Grab a list of subjects for the dialog box
IRepository<Subject> subjectRepository = new Repository<Subject>();
List<Subject> subjects = subjectRepository.GetAll().OrderBy(t => t.Position).ToList();
subjects.Insert(0, new Subject() { ID = 0, Name = "- Please Select -" });
// Add this line
// Make sure you use the correct ID for the "Other" subject
subjects.Add(new Subject() { ID = 100, Name = "Other" });
// If you determine the ID based on the list, simply set the ID = subjects.Count + 1
int otherID = subjects.Count + 1;
subjects.Add(new Subject() { ID = otherID, Name = "Other" });
ViewData["Subjects"] = subjects;
}

Categories

Resources