[SOLVED] Model binding / ViewModel binding in ASP.Net Core MVC

Issue

Let’s start with simple code:

public class SomeViewModel 
{
    public int State { get; set; }
}

public class SomeController : Controller
{
    public IActionResult DoSomething(int state)
    {
        var viewModel = new SomeViewModel();
        
        if(state % 2 == 0)
            viewModel.State = state * 2;
        else
            viewModel.State = state;
        
        return View("MyView", viewModel)
    }
}

MyView.cshtml:

@model SomeViewModel;

...
    <form method="get" asp-action="BlablaAction" asp-controller="OtherController">
        <input asp-for="State">
        <button type="submit">Save</button>
    </form>

...

I’m making requests:

/some/dosomething?state=4 => input value = 4

/some/dosomething?state=5 => input value = 5

/some/dosomething?state=6 => input value = 6

/some/dosomething?state=7 => input value = 7

but according to my logic in DoSomething action it should be:

/some/dosomething?state=4 => input value = 8

/some/dosomething?state=5 => input value = 5

/some/dosomething?state=6 => input value = 12

/some/dosomething?state=7 => input value = 7

My question is: Why input value is assigned to query param instead of property of passed model object…
And second thing I know i can change name of param from state to param1 but maybe there is other way to do it…
I’ve read 2 books about ASP.net core and haven’t encounter anything about that.

Solution

When<input asp-for="">label complied to HTML,it get value from ModelState before get value from your viewmodel,so you could clear the value in ModelState

public IActionResult DoSomething(int state)

        {
            var viewModel = new SomeViewModel();

            if (state % 2 == 0)
            {
                viewModel.State = state * 2;
                ModelState.Clear();
            }
            else
                viewModel.State = state;
           
            return View(viewModel);
        }

Also,you could keep the codes in controller,and just modify the label:

<input type="number" data-val="true" data-val-required="The State field is required." id="State" name="State" value="@Model.State">

Answered By – Ruikai Feng

Answer Checked By – David Marino (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *