Return State and city on Drop down list in ASP .NET Core

2k Views Asked by At

I Created a form on my Asp.core project.Now I want to add a drop down list for show states and city on that form.

I create a model and view model:

    [Required(ErrorMessage = "Required")]

    public string Title { get; set; }

    public long? ParentId { get; set; }


    public bool IsDeleted { get; set; }

    
    public bool IsActive { get; set; }

and write some method to access it on my repository and service:

Repository:

  public async Task<List<UserLocationViewModel>> GetStateForUserInfo()
    {
        return await _context.Locations.Where(l => l.ParentId == null)
            .Select(l => new UserLocationViewModel()
            {
                Title = l.Title,

            }).ToListAsync();
    }

    public async Task<List<UserLocationViewModel>> GetCityForUserInfo(long locationId)
    {
      return await _context.Locations.Where(l => l.ParentId == locationId)
            .Select(l => new UserLocationViewModel()
            {
                Title = l.Title,

            }).ToListAsync();
    }

and service:

    public async Task<List<UserLocationViewModel>> GetStateForUserInfo()
    {
       return await _packageRepository.GetStateForUserInfo();
    }

    public async Task<List<UserLocationViewModel>> GetCityForUserInfo(long locationId)
    {
        return await _packageRepository.GetCityForUserInfo(locationId);
    }

then on controller I call these method and return to view with view data:

  ViewData["State"] = _packageService.GetStateForUserInfo();
     
  ViewData["City"] = _packageService.GetCityForUserInfo(packageId);

in view I call it :

@{
ViewData["Title"] = _localizer["GetUserInfo"];
IEnumerable<UserLocationViewModel> State = ViewData["State"] as IEnumerable<UserLocationViewModel>;
IEnumerable<UserLocationViewModel> city = ViewData["City"] as IEnumerable<UserLocationViewModel>;

}

But when I want to access it on select tag I cant access to my properties:

                            <select   asp-for= "?????"   class="form-control  ">
                             
                            </select>

enter image description here


UPDATE: First read my repository to get location Id: but I have error

then in controller I need the id so I write:

var firstLocationId = state.FirstOrDefault()?.Id;
        var city = await _packageService.GetCityForUserInfo(firstLocationId);
        ViewData["City"] = new SelectList(city, "Title", "Title");
1

There are 1 best solutions below

11
Rena On

Here is a sample you could follow:

Model:

public class UserLocationViewModel
{
    public string Title { get; set; }
    public string City { get; set; }     //if you do not need post selected city or state
    public string State { get; set; }   //it is no need add these two properties
}
public class Location
{
    public long Id { get; set; }
    public string Title { get; set; }
    public long? ParentId { get; set; }
    public bool IsDeleted { get; set; }
    public bool IsActive { get; set; }
}

View:

For public SelectList(IEnumerable items, string dataValueField, string dataTextField);, the first parameter is the source, the second parameter is each option value in select, the third parameter is that each option displays text in html.

enter image description here

@model UserLocationViewModel
@{
    IEnumerable<UserLocationViewModel> State = ViewData["State"] as IEnumerable<UserLocationViewModel>;
    IEnumerable<UserLocationViewModel> city = ViewData["City"] as IEnumerable<UserLocationViewModel>;
}

<select asp-items="@(new SelectList(State,"Title","Title"))" class="form-control">
</select>

<select  asp-items="@(new SelectList(city,"Title","Title"))" class="form-control">
</select>

Controller:

[HttpGet]
public async Task<IActionResult> Index()
{
    ViewData["State"] = _packageService.GetStateForUserInfo();    
    ViewData["City"] = _packageService.GetCityForUserInfo(packageId);
    return View();
}

If you want to post the selected city or state to controller:

Index.cshtml:

The mapped property in asp-for should be the same type with dataValueField(Title here).

@model UserLocationViewModel
@{
    IEnumerable<UserLocationViewModel> State = ViewData["State"] as IEnumerable<UserLocationViewModel>;
    IEnumerable<UserLocationViewModel> city = ViewData["City"] as IEnumerable<UserLocationViewModel>;
}
<form method="post">
    <select asp-for="State" asp-items="@(new SelectList(State,"Title","Title"))" class="form-control">
    </select>

    <select asp-for="City" asp-items="@(new SelectList(city,"Title","Title"))" class="form-control">
    </select>
    <input type="submit" value="Post" />
</form>

Controller:

[HttpGet]
public async Task<IActionResult> Index()
{
    ViewData["State"] = _packageService.GetStateForUserInfo();     
    ViewData["City"] = _packageService.GetCityForUserInfo(packageId);
    return View();
}
[HttpPost]
public IActionResult Index(UserLocationViewModel model)
{
    return View();
}

Result:

enter image description here


Update:

Two ways display dropdownlist:

First one:

ViewData["State"] = new List<SelectListItem>
{
    new SelectListItem{Text = "Value1", Value = "1"},
    new SelectListItem{Text = "Value2", Value = "2"},
    new SelectListItem{Text = "Value3", Value = "3"},
    new SelectListItem{Text = "Value4", Value = "4"}
}

Razor view:

<select asp-items="(IEnumerable<SelectListItem>)@ViewData["State"]" class="form-control">
</select>

Second one:

ViewData["State"] = await Locations.Where(l => l.ParentId == null)
                                    .Select(l => new UserLocationViewModel()
                                    {
                                        Title = l.Title,

                                    }).ToListAsync();

Razor view:

@{
IEnumerable<UserLocationViewModel> State = ViewData["State"] as IEnumerable<UserLocationViewModel>;   
 }
<select asp-items="@(new SelectList(State,"Title","Title"))" class="form-control">
</select>