Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Route Id overrides Model.Id

I have a route like this:

Conference/Committees/1

And within that page, it cycles through the Committees for a Conference (where the Conference Id = 1).

I have a partial view that renders an edit style page for a selected committee, with a route like this:

Conference/Committees/1?committeeId=2

In debug, the model data is correct, and the Committee has an Id = 2. However, when I use the following Razor statement:

@Html.HiddenFor(model => model.Id)

with the following model:

@model munhq.Models.Committee

The hidden input has an value of "1" instead of "2".

Is this a bug in MVC? Or am I doing something wrong?

Update

If I replace

@Html.HiddenFor(model => model.Id)

with

<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Id" name="Id" type="hidden" value="@Model.Id" />

it renders the correct Id value.

Update 2

    public async Task<ActionResult> Committees(int id, PrivilegedAction? actionToTake, int? committeeId, ConferenceStatusMessage? csm)
    {
        Conference conference;
        HandleConferenceStatusMessage(csm);

        try
        {
            conference = await db.Conferences
            .Include(i => i.Committees.Select(c => c.CommitteeMemberCommitteeEntries))
            .Where(i => i.Id == id)
            .SingleAsync();

            HandleAction(actionToTake, conference);
            HandleAuthorisations(conference);
        }
        catch
        {
            return ConferenceActionFail();
        }

        if (committeeId == null)
        {
            if (conference.Committees.FirstOrDefault() == null)
            {
                committeeId = 0;
            }
            else
            {
                committeeId = conference.Committees.FirstOrDefault().Id;
            }

            ViewBag.ConferenceId = id; // used for adding a committee member entry

            return RedirectToAction("Committees", new { id = id, action = actionToTake, committeeId = committeeId, csm = csm });
        }
        else
        {
            if (CommitteeIsPartOfConference(conference, committeeId) || committeeId == 0)
            {
                ViewBag.SelectedCommittee = committeeId;
                ViewBag.JsonAvailableMembers = jsonAvailableCommitteeMembers(id);

                return View(conference);
            }
            else
            {
                return HttpNotFound();
            }
        }
    }
like image 522
David Poxon Avatar asked Feb 14 '23 23:02

David Poxon


1 Answers

Try using this before returning a view:

ModelState.Clear();

In general when an Action gets called the framework builds a ModelStateCollection based on the query-string values, post-data, routing values etc. And this ModelStateCollection will be passed to the View. All the HTML input helpers try to the get the values from the ModelStateCollection first, before trying to get the values from the actual model. And that's the reason why your Html.HiddenFor extension works incorrectly (it checks for ModelStateCollection firstly) whereas your <input type="hidden"> contains a correct value.

like image 67
Paweł Bejger Avatar answered Feb 23 '23 12:02

Paweł Bejger