fill #html.dropdownlist from other #html.dropdownlist by same table using ajax - asp.net-mvc-4

I'm working on some search/filter functionality by using dropdownlists
the question is how can i populate the second dropdownlist by choosing item in first ddl
if all data saved in ont table.
i have table of CarType that has manufacturer, model and year.
when i choose a manufacturer in first ddl the second will filled by models of this manufacturer.
Code i have in Controller:
public ActionResult Search(string manufacturer, string carModel, string searchString, string gear)
{
using (CarTypesLogic logic = new CarTypesLogic())
{
IEnumerable<CarType> allCarTypes = logic.GetAllCarTypes();
var manufacturerList = new List<string>();
var modelList = new List<string>();
var gearList = new List<string>();
var foundManufacturer = from maker in allCarTypes
orderby maker.Manufacturer
select maker.Manufacturer;
var foundModels = from model in allCarTypes
orderby model.Model
select model.Model;
var foundGears = from transmission in allCarTypes
select transmission.Gear;
manufacturerList.AddRange(foundManufacturer.Distinct());
modelList.AddRange(foundModels.Distinct());
gearList.AddRange(foundGears.Distinct());
ViewBag.Manufacturer = new SelectList(manufacturerList);
ViewBag.Gear = new SelectList(gearList);
ViewBag.carModel = new SelectList(modelList);
var foundCars = from car in allCarTypes select car;
if (!String.IsNullOrEmpty(manufacturer))
{
foundCars = foundCars.Where(car => car.Manufacturer == manufacturer);
}
if (!String.IsNullOrEmpty(gear))
{
foundCars = foundCars.Where(car => car.Gear == gear);
}
if (!String.IsNullOrEmpty(searchString))
{
foundCars = foundCars.Where(car => car.Manufacturer.ToLower().Contains(searchString.ToLower()));
}
if (!String.IsNullOrEmpty(carModel))
{
foundCars = foundCars.Where(car => car.Model == carModel);
}
return View(foundCars);
}
}
My cshtml code:
#using (Html.BeginForm())
{
<p>
Manufacturer: #Html.DropDownList("manufacturer", String.Empty)
Model: #Html.DropDownList("carModel",String.Empty)
Gear: #Html.DropDownList("gear", String.Empty)
Free Type: #Html.TextBox("SearchString")
<br />
<input type="submit" value="Search"/>
</p>
}

you need to use Cascaded DropDownList.
here are few examples:
http://mvc4beginner.com/Sample-Code/Cascading-DropDownList/APS-.NET-MVC-Cascading-DropdownLists-Using-LINQ.html
http://code.msdn.microsoft.com/Cascading-DropDownList-in-833683f9/sourcecode?fileId=48387&pathId=451527572
http://www.itorian.com/2013/02/cascading-dropdownlist-in-aspnet-mvc.html

Related

How to write a tag-helper for alphabetical paging

I came across the following article https://www.mikesdotnetting.com/article/256/entity-framework-recipe-alphabetical-paging-in-asp-net-mvc describing how to generate paging links from the data instead of the alphabet in a asp.net application.
The solution shown here is based on html helpers.
How can I implement this feature using tag helpers instead?
I'm using asp.net core 1.1.
The code I'm referrig to is:
public static class HtmlHelpers
{
public static HtmlString AlphabeticalPager(this HtmlHelper html, string selectedLetter, IEnumerable<string> firstLetters, Func<string, string> pageLink)
{
var sb = new StringBuilder();
var numbers = Enumerable.Range(0, 10).Select(i => i.ToString());
var alphabet = Enumerable.Range(65, 26).Select(i => ((char)i).ToString()).ToList();
alphabet.Insert(0, "All");
alphabet.Insert(1, "0-9");
var ul = new TagBuilder("ul");
ul.AddCssClass("pagination");
ul.AddCssClass("alpha");
foreach (var letter in alphabet)
{
var li = new TagBuilder("li");
if (firstLetters.Contains(letter) || (firstLetters.Intersect(numbers).Any() && letter == "0-9") || letter == "All")
{
if (selectedLetter == letter || selectedLetter.IsEmpty() && letter == "All")
{
li.AddCssClass("active");
var span = new TagBuilder("span");
span.SetInnerText(letter);
li.InnerHtml = span.ToString();
}
else
{
var a = new TagBuilder("a");
a.MergeAttribute("href", pageLink(letter));
a.InnerHtml = letter;
li.InnerHtml = a.ToString();
}
}
else
{
li.AddCssClass("inactive");
var span = new TagBuilder("span");
span.SetInnerText(letter);
li.InnerHtml = span.ToString();
}
sb.Append(li.ToString());
}
ul.InnerHtml = sb.ToString();
return new HtmlString(ul.ToString());
}
}
Any idea how to proceed?

There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key '****'. [duplicate]

This question already has answers here:
The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'
(6 answers)
Closed 4 years ago.
Im trying to do a dropdownlist of Student Enrollments at Student index page.
Student Controller:
public ActionResult Index(string studentEnrollment, string sortOrder, string currentFilter, string searchString, int? page)
{
ViewBag.CurrentSort = sortOrder;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
if (searchString != null)
{
page = 1;
}
else
{
searchString = currentFilter;
}
ViewBag.CurrentFilter = searchString;
var students = studentService.GetAll();
//var students = from s in studentService.GetAll()
// select s;
var studentViewModel = Mapper.Map<IEnumerable<Student>, IEnumerable<StudentViewModel>>(students);
if (!String.IsNullOrEmpty(searchString))
{
students = students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())
|| s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
}
switch (sortOrder)
{
case "name_desc":
students = students.OrderByDescending(s => s.LastName);
break;
case "Date":
students = students.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
students = students.OrderByDescending(s => s.EnrollmentDate);
break;
default:
students = students.OrderBy(s => s.LastName);
break;
}
List<Course> courses = new List<Course>();
SelectList studentEnrollment = new SelectList(courses, "CourseID", "Title");
ViewBag.Courses = studentEnrollment;
//if (!string.IsNullOrEmpty(studentEnrollment))
// students = students.Where(m => m.Course.Title == studentEnrollment);
int pageSize = 3;
int pageNumber = (page ?? 1);
return View(students.ToPagedList(pageNumber, pageSize));
}
View:
#using (Html.BeginForm("Index", "Student", FormMethod.Get))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<p>
Find by name: #Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
Enrollment: #Html.DropDownList("Course", (IEnumerable<SelectListItem>)ViewBag.Courses, "Select Course")
<input type="submit" value="Filter" />
</p>
}
error at line:
Enrollment: #Html.DropDownList("Course", (IEnumerable)ViewBag.Courses, "Select Course")
What Im doing wrong?
I have seen a lot of questions where people have had issues with the drop down list and it was because of the view bag. Everything I have seen says you should try to avoid using ViewBag for drop downs. What I would suggest instead is to put your list in your viewmodel.
Public List<SelectListItem> CourseList { get; set; }
I am not seeing in your code where you are populating your course list. On your controller instead of setting the viewbag set this parameter. Something like
foreach(var temp in CourseList){ //Course list being pulled from the database or wherever that data exists
model.CourseList.Add(new SelectListItem{ Text = temp.Name, Value = temp.Value });
}
then on your view your drop down list would be changed to
#Html.DropDownList("Course", Model.CourseList, "Select Course")

Binding The Collection of data in drop down list in mvc4

I am having Code like below in my view.
#if (!Model.DisableBuyButton || !Model.DisableWishlistButton)
{
<div class="qutblk">
<span>#Html.LabelFor(model => model.EnteredQuantity, new { #class = "input-small" }, " :")</span>
#if (Model.AllowedQuantities.Count > 0)
{
#Html.DropDownListFor(model => model.EnteredQuantity, Model.AllowedQuantities, new { #class = "input-small" })
}
else
{
#Html.TextBoxFor(model => model.EnteredQuantity, new { #class = "input-small" })
}
} #Html.Widget("productdetails_add_info")
</div>
Here if i have the ALLOWEDQUANTITIES.COUNT is more then 0.I need drop down list for quantities.
For example if the quantity is 5 i need 1,2,3,4,5 numbers in my drop down list.And if the quantity is 7 i need 1,2,3,4,5,6,7 numbers in my drop down.
But my problem is i am not able to bind the data like numbers in my drop down that means if the quantity is 5 it simply displaying only 5 number in drop down list not displaying 1,2,3,4,5.
You may try something like this:
public static class MyLists
{
public static List<SelectListItem> GetList()
{
List<SelectListItem> result = new List<SelectListItem>(int AllowedQuantities)
for(int i = 0; i < AllowedQuantities; i++)
{
var number = i + 1;
var item = new SelectListItem {text = number.ToString(), value = number.ToString()};
result.Add(item);
}
return result
}
}
In your view:
#Html.DropDownListFor(model => model.EnteredQuantity, MyLists.GetList(model.EnteredQuantity), new { #class = "input-small" })

Iterate through collection of List<object>

I have what is probably simple problem, but I am stumped. I call a method from another assembly that returns me a List<object>, this data is Excel spreadsheet data queried using LinqToExcel. Under the scenes, that collection is actually a List<LinqToExcel.Cell>. In LinqToExcel, that makes up a LinqToExcel.Row. I want to be able to bind this data to a Telerik ASP.NET MVC grid for viewing. Here's my controller code:
TypeOfServiceCodeListingDetailViewModel model = new TypeOfServiceCodeListingDetailViewModel();
model.Excel_Data = new List<LinqToExcel.Row>();
using (LinqToExcelReader reader = new LinqToExcelReader(fileName, true))
{
previewData = reader.ReadRawDataByPage(5, 0);
foreach (LinqToExcel.Row item in previewData)
{
model.Excel_Data.Add(item);
}
return View(new GridModel(model.Excel_Data));
}
And in my view:
#(Html.Telerik().Grid(Model.Excel_Data)
.Name("Grid2")
.HtmlAttributes(new { style = "width:400px;" })
.DataBinding(dataBinding => dataBinding.Ajax().Select("GetExcelData", "TypeOfService"))
.Columns(columns =>
{
columns.AutoGenerate(column =>
{
column.Width = "150px";
});
}))
Here's what my grid has headers like the below with no data:
Capacity Count
Thanks for the help!
Here's the code that solved my problem. I'm sure there's a better approach.
using (LinqToExcelReader reader = new LinqToExcelReader(modelDetail.FileName, true))
{
var previewData = reader.ReadRawDataByPage(5, 0);
List<List<string>> masterList = new List<List<string>>();
for (int x = 0; x < previewData.Count; x++)
{
List<string> list = new List<string>();
foreach (var cell in (LinqToExcel.Row)previewData[x])
{
list.Add(cell);
}
masterList.Add(list);
}
var listTest = masterList;
modelDetail.ExcelData = new List<ExcelData>();
foreach (List<string> theList in masterList)
{
ExcelData xlsData = new ExcelData();
xlsData.Column1 = theList[0];
xlsData.Column2 = theList[1];
xlsData.Column3 = theList[2];
xlsData.Column4 = theList[3];
xlsData.Column5 = theList[4];
xlsData.Column6 = theList[5];
xlsData.Column7 = theList[6];
xlsData.Column8 = theList[7];
xlsData.Column9 = theList[8];
xlsData.Column10 = theList[9];
modelDetail.ExcelData.Add(xlsData);
}

Why does this controller double the inserts when I try to archive the results of the Bing Search API?

I'm trying to archive my search results for a term by
Using the Bing API in an async controller
Inserting them into database using Entity Framework
using the Bing API and insert them into a database using entity framework. For whatever reason it is returning 50 results, but then it enters 100 results into the database.
My Controller Code:
public class DHWebServicesController : AsyncController
{
//
// GET: /WebService/
private DHContext context = new DHContext();
[HttpPost]
public void RunReportSetAsync(int id)
{
int iTotalCount = 1;
AsyncManager.OutstandingOperations.Increment(iTotalCount);
if (!context.DHSearchResults.Any(xx => xx.CityMarketComboRunID == id))
{
string strBingSearchUri = #ConfigurationManager.AppSettings["BingSearchURI"];
string strBingAccountKey = #ConfigurationManager.AppSettings["BingAccountKey"];
string strBingUserAccountKey = #ConfigurationManager.AppSettings["BingUserAccountKey"];
CityMarketComboRun cityMarketComboRun = context.CityMarketComboRuns.Include(xx => xx.CityMarketCombo).Include(xx => xx.CityMarketCombo.City).First(xx => xx.CityMarketComboRunID == id);
var bingContainer = new Bing.BingSearchContainer(new Uri(strBingSearchUri));
bingContainer.Credentials = new NetworkCredential(strBingUserAccountKey, strBingAccountKey);
// now we can build the query
Keyword keyword = context.Keywords.First();
var bingWebQuery = bingContainer.Web(keyword.Name, "en-US", "Moderate", cityMarketComboRun.CityMarketCombo.City.Latitude, cityMarketComboRun.CityMarketCombo.City.Longitude, null, null, null);
var bingWebResults = bingWebQuery.Execute();
context.Configuration.AutoDetectChangesEnabled = false;
int i = 1;
DHSearchResult dhSearchResult = new DHSearchResult();
List<DHSearchResult> lst = new List<DHSearchResult>();
var webResults = bingWebResults.ToList();
foreach (var result in webResults)
{
dhSearchResult = new DHSearchResult();
dhSearchResult.BingID = result.ID;
dhSearchResult.CityMarketComboRunID = id;
dhSearchResult.Description = result.Description;
dhSearchResult.DisplayUrl = result.DisplayUrl;
dhSearchResult.KeywordID = keyword.KeywordID;
dhSearchResult.Created = DateTime.Now;
dhSearchResult.Modified = DateTime.Now;
dhSearchResult.Title = result.Title;
dhSearchResult.Url = result.Url;
dhSearchResult.Ordinal = i;
lst.Add(dhSearchResult);
i++;
}
foreach (DHSearchResult c in lst)
{
context.DHSearchResults.Add(c);
context.SaveChanges();
}
AsyncManager.Parameters["message"] = "The total number of results was "+lst.Count+". And there are " + context.DHSearchResults.Count().ToString();
}
else
{
AsyncManager.Parameters["message"] = "You have already run this report";
}
AsyncManager.OutstandingOperations.Decrement(iTotalCount);
}
public string RunReportSetCompleted(string message)
{
string str = message;
return str;
}
}
Here is how I am calling it from my asp.net mvc 4 page.
#Ajax.ActionLink("Run Report", "GatherKeywordsFromBing", "DHWebServices",
new { id=item.CityMarketComboRunID},
new AjaxOptions { OnSuccess = "ShowNotifier();", UpdateTargetId = "TopNotifierMessage", HttpMethod = "POST", InsertionMode = InsertionMode.Replace, LoadingElementId = strCityMarketComboProgressID, LoadingElementDuration = 1000 },
new { #class = "ViewLink" })
<span class="ProgressIndicator" id="#strCityMarketComboProgressID"><img src="#Url.Content("~/Content/img/SmallBall.gif")" alt="loading" /></span>
For whatever reason all of
Try saving only once:
foreach (DHSearchResult c in lst)
{
context.DHSearchResults.Add(c);
}
context.SaveChanges();
Also there's nothing asynchronous in your code, so there's no point of using asynchronous controller. Not only that it won't improve anything but it might make things worse.