Have Selected Dropdown Appear on Edit Razor Page

Viewed 78

NOTE: REVISED FROM ORIGINAL POST. SOME OF THE MODEL/PROPERTY names have changed with more editing.

I have a create page which will utilizes a couple of dropdown lists. For the edit page, I would like the selected value from the create page to appear as the selected dropdown choice, but would still like it to be a dropdown list of all values so that users could select a new value if the value selected on the create page was incorrect.

For example, if a user selected 'peaches' from a dropdown list of 'apples', 'peaches' and 'pears' on the create page and posted it, when they go to the edit page, I would like the dropdown list to show 'peaches', as the selected value, but allow the user to pick 'apples' or 'pears' if they wished to change it.

Here is what I have on my edit.cshtml page for my dropdown lists (both are set up the same way):

<td style="width: 25%">
   <div class="mb-3">
      <label asp-for="InfoSite.Specialty"></label>
      <select asp-for="InfoSite.Specialty" id="Select1" class="form-select"> 
         <option value="">---Select Specialty---</option>
         @foreach(var item in Model.DisplayMDSpecialtyData)
             {
               <option value="@item.ID" selected="@(item.ID.ToString()==Model.InfoSite.Specialty?true:false)" disabled="@(item.ID.ToString()==Model.InfoSite.Specialty?true:false)">@item.Description</option>
             }
       </select>
   </div>
</td>
<td style="width: 25%">
   <div class="mb-3">
       <label asp-for="InfoSite.ResType"></label>                      
       <select asp-for="InfoSite.ResType" id="Select2" class="form-select">
           <option value="">---Select Residence Type---</option>
           @foreach(var item in Model.DisplayResTypeData)
              {
                 <option value="@item.ID" selected="@(item.ID.ToString()==Model.InfoSite.ResType?true:false)" disabled="@(item.ID.ToString()==Model.InfoSite.ResType?true:false)">@item.Description</option>
              }
        </select>
    </div>
</td>

And here is what I have on my edit.cshtml.cs (includes info for the 2 dropdowns):

namespace PHECWeb.Pages.InfoSites;

[BindProperties]

public class EditModel : PageModel
{
    private readonly ApplicationDbContext _db;
    public InfoSite InfoSite { get; set; }
    public EditModel(ApplicationDbContext db)
    {
        _db = db;
    }

    public IEnumerable<ResType> DisplayResTypeData { get; set; }
    public IEnumerable<MDSpecialty> DisplayMDSpecialtyData { get; set;  }

    public async void OnGet(int? ID)
    {
        InfoSite = _db.InfoSite.Find(ID);
        DisplayResTypeData = await _db.ResType.ToListAsync();
        DisplayMDSpecialtyData = await _db.MDSpecialty.ToListAsync();
    }

    public async Task<IActionResult> OnPost()
    {
        if (ModelState.IsValid)
        {
            _db.InfoSite.Update(InfoSite);
            await _db.SaveChangesAsync();
            TempData["success"] = "Site Information updated successfully.";
            return RedirectToPage("Index");
        }
        return Page();
    }
}

I am getting the dreaded System.NullReferenceException: 'Object reference not set to an instance of an object.' on the @foreach(var item in Model.DisplayMDSpecialtyData).

System.NullReferenceException Error

I desperately need help to get past this. :( Would someone please be able to add some insight (in layman's terms as I am a newbie to all of this) as to what edits I would need to this code to rid myself of this error? I have Googled and YouTubed, but because my knowledge level is so low at this point, I don't understand much of what I am seeing. I understand the concept, I just don't understand the placement of a fix (view vs .cs) or the exact syntax of a fix. Trying my best to learn and as stated above, asking the question was only after MUCH searching on my own. Please be kind.

2 Answers

You need to know the following things:

Firstly, by using your current code your select will generate the option value which match the ID value and the option text which match the Description value.

<select>
    <option value="ID1">Description1</option>
    <option value="ID2">Description2</option>
    //....
</select>

Then the asp-for="InfoSite.ResType" matches the selected option value which is the ID value of ResCategory. So you need be sure the value of ResType and ID should keep same.

Finally, for the Edit page, If the InfoSite.ResType's value is same with one of the option value(ID value). The dropdownlist will automatically make this option selected. But the disabled cannot do like this way.

Here is a whole working demo you could follow:

Model

public class ResCategory
{
    public int ID { get; set; }
    public string? Description { get; set; }
}
public class InfoSite
{ 
    public int ID { get; set; }
    public string? ResType { get; set; }
}

View

<select asp-for="InfoSite.ResType" id="Select2" class="form-select">
    <option value="">---Select Residence Type---</option>
    @foreach(var item in Model.DisplayResCatData)
    {
        <option value="@item.ID" selected="@(item.ID.ToString()==Model.InfoSite.ResType?true:false)" disabled="@(item.ID.ToString()==Model.InfoSite.ResType?true:false)">@item.Description</option>
    }
</select>

PageModel

public class EditModel : PageModel
{
    public IEnumerable<ResCategory> DisplayResCatData { get; set; }
    public InfoSite InfoSite { get; set; }
    public void OnGet(int? id)
    {
        //for easy testing, I just hard coded here......
        //InfoSite = await _db.InfoSite.FindAsync(id);
        InfoSite = new InfoSite()
        {
            ID = 1,
            ResType = "2"
        };
        DisplayResCatData = new List<ResCategory>()
        {
            new ResCategory(){ID=1,Description="aa"},
            new ResCategory(){ID=2,Description="bb"},
            new ResCategory(){ID=3,Description="cc"}
        };
    }
}

This was another stumper with a very simple change to make the code work.

<option value="@item.ID" selected="@(item.ID.ToString()==Model.InfoSite.Specialty?true:false)" disabled="@(item.ID.ToString()==Model.InfoSite.Specialty?true:false)">@item.Description</option>

Just needed the "disabled=..." removed to look like this:

<option value="@item.ID" selected="@(item.ID.ToString()==Model.InfoSite.Specialty?true:false)">@item.Description</option>

And then the selected value displays on the Edit page just fine.

Related