Click here to Skip to main content
15,916,398 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a MVC application to capture the skills (aka Capabilities) and skill scores for a user.

ViewModel = 'ScoresViewModel' and contains models for skills and scores.

public class ScoresViewModel
    {
        public List<ScoreModel> Scores { get; set; }
        public List<CapabilitiesModel> Capabilities { get; set; }
        
    }


ScoreModel:
public class ScoreModel
    {

        public int Id { get; set; }
        public int Capability { get; set; }
        public byte Score { get; set; }

       
    }


Capability Model:
public class CapabilitiesModel
    {
        public int Id { get; set; }
        public string CapabilityName { get; set; }
        public string Description { get; set; }


    }


I'm able to bring back (through my Web Api) the list of skills and display them through a HTML Table, but I need to capture scores for each of those skills in the Web UI (HTML\Blazor).




My UI:
@model CapabilityTracker.ViewModels.ScoresViewModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

<table class="table">
    <tr>
        <th>
            Capability Name
        </th>
        <th>
            Score
        </th>
    </tr>

    @foreach (var item in Model.Capabilitites)
    {

<tr>
    <td>
        @Html.DisplayFor(modelItem => item.Id)
        @Html.DisplayFor(modelItem => item.CapabilityName)


    </td>
   
    <td>
        <input type="number" min="0" max="5" step="1" name="txtScore" />

    </td>
    
</tr>
    }


</table>
}



Im struggling to understand how I extract the data from the table and populate the ScoresModel (or to be more specific a List of ScoreModels with the data from the table..

Because the Scores model is essentially empty at the time of page launch and because there will be multiple score models (each skill holding a single score) in a submission - i cant bind to anything (i dont think) so i need to build the list of ScoreModels from the data in the HTML table..

Hoping you guys can help

What I have tried:

SEE CODE SNIPPETS IN QUESTION

Ive been unsuccessful trying to understand how I populate a list or collection of Score Models to push back through the POST API
Posted
Updated 21-Dec-22 22:46pm

1 solution

I'd suggest you alter your view-model to match the requirements of your view. You can then use server-side code to map the posted view-model to the required model data.

For example:
C#
public class ScoresViewModel
{
    public List<CapabilityScoreViewModel> Scores { get; set; }
}

public class CapabilityScoreViewModel
{
    public int Id { get; set; }
    public string CapabilityName { get; set; }
    
    [Required, Range(1, 5)]
    public byte? Score { get; set; }
}
Razor
@model CapabilityTracker.ViewModels.ScoresViewModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    <table class="table">
    <thead>
    <tr>
        <th scope="col">
            Capability Name
        </th>
        <th scope="col">
            Score
        </th>
    </tr>
    </thead>
    <tbody>
    @for (int index = 0; index < Model.Scores.Count; index++)
    {
        <tr>
            <th scope="row">
                @Html.HiddenFor(m => m.Scores[index].Id)
                @Html.HiddenFor(m => m.Scores[index].CapabilityName)
                @Html.DisplayFor(m => m.Scores[index].Id)
                @Html.DisplayFor(m => m.Scores[index].CapabilityName)
            </th>
            <td>
                @Html.EditorFor(m => m.Scores[index].Score)
            </td>
        </tr>
    }
    </tbody>
    </table>
    
    <p>
        <button type="submit">
            Create
        </button>
    </p>
}
C#
[HttpGet]
public ActionResult CreateScores()
{
    List<CapabilitiesModel> capabilities = ...; // TODO: List the capabilities
    
    ScoresViewModel model = new ScoresViewModel
    {
        Scores = capabilities
            .Select(c => new CapabilityScoreViewModel
            {
                Id = c.Id,
                CapabilityName = c.CapabilityName,
            })
            .ToList(),
    };
    
    return View(model);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateScores(ScoresViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    
    List<ScoreModel> scores = model.Scores
        .Select(s => new ScoreModel
        {
            Capability = s.Id,
            Score = s.Score.GetValueOrDefault(),
        })
        .ToList();
    
    ... // TODO: Save the scores
}
 
Share this answer
 
Comments
Graeme_Grant 22-Dec-22 5:05am    
I was wondering if he means Razor and not Blazor...
Richard Deeming 22-Dec-22 5:08am    
Good catch. I haven't done much with Blazor, but I suspect the approach will be similar.
Graeme_Grant 22-Dec-22 5:11am    
Just be aware that Blazor binding does not work the same as WPF/Xamarin/MAUI, so MVVM works much differently. This is the best lib that I have found that will get you close: GitHub - klemmchr/MvvmBlazor: A lightweight Blazor Mvvm Library[^]

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900