Friday, 7 October 2011

Where Does MVC3 Look For the Entity.ID within the View

Working with Razor Engine Views created by default after clicking 'Add View' from with a Controller Action Method.

Found that the 'Edit' views included the Entity ID in the markup allowing users to directly edit the primary key of the field - not cool.

So i deleted them - also, not cool.

Doing so resulted in this Exception:

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

Which upon debugging the Action Method, which was expecting an instance of my entity to be passed in, i found the entity was NULL and then this post alerted me to the fact that .Net couldn't find an ID and so didn't know which entity to pass in.

So, i need to be able to ensure that the ID is available for the runtime to instanitate the correct Model Entity and pass it into the Controller Action Method > hence I added the original markup back in:

<div class="editor-label">
    @Html.LabelFor(model => model.EMERGENCY_SERVICE_TYPE_ID)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.EMERGENCY_SERVICE_TYPE_ID)
    @Html.ValidationMessageFor(model => model.EMERGENCY_SERVICE_TYPE_ID)
</div>

BUT: where, exactly is .Net getting the ID from ???

It appears that .Net is ripping the ID out of this HTML Helper:

@Html.EditorFor(model => model.EMERGENCY_SERVICE_TYPE_ID)

When you inspect the HTML at the client, you'll find that the above Helper will render the HTML as:

<input id="EMERGENCY_SERVICE_TYPE_ID" class="text-box single-line" type="text" 
 value="23" name="EMERGENCY_SERVICE_TYPE_ID"  
 data-val-required="The EMERGENCY_SERVICE_TYPE_ID field is required." 
 data-val-number="The field EMERGENCY_SERVICE_TYPE_ID must be a number." 
 data-val="true">

After some playing around eliminating various attributes i found that in order for .Net to automatically take the form values (hence the ID needs to be in an <input> tag) and use them to instanitate a Model Entity for you, use the following markup:

<input type="hidden" 
name="EMERGENCY_SERVICE_TYPE_ID" 
value="@this.Model.EMERGENCY_SERVICE_TYPE_ID" 
id="estId" />

Note the Razor Syntax (@this.Model) could be replaced with ye olde Server Side code syntax (<%=).

You could do it using a HTML Helper (eg HTML.HiddenFor(x => x.ID)) but that would also include a bunch of unnecessary stuff in the markup.

The mandatory requirements in order for .Net to instantiate your Entity:
  • The ID needs to be wrapped up in an <input>  tag
  • The 'name' attribute of the <input> tag needs to exactly the same as the Entity Property which represents the Primary Key

No comments:

Post a Comment