Mvc Model Bind in View? - asp.net-mvc

I have a model..
Models.Mm.Items.ItemEditModel like thiss..
in ItemEdit View
#Html.TextBoxFor(m => m.RecordTypeId) --> this works bind model and take value RecordTypeId
#Html.Kendo().NumericTextBoxFor(m => m.RecordTypeId) --> this works
<input id="RecordTypeId" name="RecordTypeId" type="text" /> --> this not working this value is null
I am using autofac and kendo.
I could not understand why html binding not working..

There is not enough information here to give you the real cause of the problem, but one thing you can check is the name attribute of the input element generated by the first two methods.
Mvc use the name attribute to bind your model so if this name does not match what he expect for the property of the mod

Related

MVC Using a custom indexer with a EditorFor

I have an EditorFor template that I call with an array of items (there may be a few) and I reference the indexes individually (not in a loop) so I can lay them out a certain way
#Html.EditorFor(x => Model.SomeViewModels[0], "SomeTemplate")
all works fine but ideally I want to reference the array by a nicer indexer
#Html.EditorFor(x => Model.SomeViewModels["Item to Find"], "SomeTemplate")
for better readability and some flexibility to cope if the index changes
so I was wondering if I could set up a custom indexer on the Model - like this
public ObjecToReturn this[string TextToFind]
{
get
{
return ObjectToReturn based on TextToFind
}
}
and it does work - and pulls the value through correctly however when I look at the Html the input fields all have names like name=[Item to Find].AnswerValue which I can see why but it messes up the post back
Just wondered if any clever person had worked out how I can send in Model.SomeViewModels["Item to Find"] to the EditorFor yet the underlying Html in the template reflects Model.SomeViewModels[0] (0 being the index of "Item to find" in the array) so the Postback works
Or maybe this is the wrong approach - I'm hoping I'm missing something straightforward.
Thanks in advance
By default the DefaultModelBinder binds collections where the indexers start at zero and are consecutive. You can make this work by adding a hidden input for a Index property (note Index is not a property of your model - its just a special value used for binding collections). For example
<input type="text" name="SomeViewModels[ABC]" value = "" />
<input type="hidden" name="SomeViewModels.Index" value="ABC" />
<input type="text" name="SomeViewModels[XYZ]" value = "" />
<input type="hidden" name="SomeViewModels.Index" value="XYZ" />
The addition of the hidden input where the value attribute matches the indexer value allows the DefaultModelBinder to correctly bind the collection

Asp Mvc one way model property, i.e. from client only

Is there an attribute or something similar in Asp MVC to indicate that a property should only come from the client, i.e. it shouldn't be roundtripped.
So
#Html.HiddenFor(x => x.MyProp)
I set this somehow on the client together with some other properties, it goes the server, server has a model error so sends it all back. I don't want this one property to be roundtripped.
The best I can think of is to do this
<input type="hidden" name=MyPropOneWay />
Then I manually insert it at the controller end into the property
(Addition)
It's not to avoid model errors, it's because there are a few ways of submitting the form, this is a shortcut method. In no circumstance do I want this value to be roundtripped as otherwise it will look like it's been set when it hasn't, however I do want everything else to be roundtripped
Thanks
If you don't want the value rendered from the server (either initially or after a roundtrip), use:
<input type="hidden" name="#Html.NameFor(m => m.MyProp)" />
This will render an input hidden element without a value, but it will still have the correct name to automatically bind to your model on form submission. Which effectively makes it "one way".
(The NameFor helper was added in MVC4)

difference in input type=Checkbox, #HTML.CheckBox and #HTML.CheckBoxFor?

I m new to MVC and confused what is difference in <Input type="Checkbox">, #HTML.CheckBox and #HTML.CheckBoxFor.
Can you please guide why two helpers are provided for same thing ? In which situation which one should be used ?
Thanks
Edit:
Added Input type=checkbox
<Input type="Checkbox"> is Html markup for a checkbox and #Html.CheckBox & #HTML.CheckBoxFor are Html Helpers for Razor view engine..
suppose your viewmodel has a property Person.HadDinner, then usually for model binding to work properly you will have to name the checkbox Person.HadDinner and id as Person_HadDinner..
you can use #Html.CheckBox like
#HTML.CheckBox("Person.HadDinner", Model.Person.HadDinner)
but if you are using #HTML.CheckBoxFor, it will be strongly typed..
#HTML.CheckBoxFor(x => x.Person.HadDinner)
in both the cases, final output markup will be
<input type="checkbox" id="Person_HadDinner" name="Person.HadDinner">
The CheckboxFor (MSDN)
Returns a check box input element for each property in the object that
is represented by an expression.
This means a checkbox element is created for each property in the expression provided. Where as Checkbox (MSDN)
Returns a check box input element by using the specified HTML helper
and the name of the form field.
This creates a simple Checkbox element with the (optional) attributes provided.
Typically when referencing a property of an object (or the View Model) the most desired technique is to use CheckboxFor as the checkbox will be formatted correctly against your model.
Hope this helps.
EDIT: Response to OP Changes.
Both the CheckboxFor and Checkbox generate standard HTML output such as below.
#Html.CheckboxFor(m => m.SomeProperty)
<input type="checkbox" name="SomeProperty" id="SomeProperty" />
#Html.Checkbox("SomeProperty")
<input type="checkbox" name="SomeProperty" id="SomeProperty" />
The helper methods simply generate the HTML required to meet the expressions and attributes defined in the helpers.
Additionally, you dont have to use the helpers. You can write your HTML elements directly as needed.

How to bind list of dynamic objects to the Model

I have a strongly typed view where one of the properties of the model that is passed in is a list of objects. I am handling dynamic binding of inputs to this list by using the BeginCollectionItem helper which works fine. However, I also want to initially have a group of inputs visible on the view that will bind to the 'first' object in the list.
I've tried just copying the inputs that BeginCollectionItem generates but that doesn't seem to work.
It generates inputs with name attributes like
invoiceItems[ef43a8f2-c6b7-4791-bf7f-6764c8e3fc9b].Description
invoiceItems[ef43a8f2-c6b7-4791-bf7f-6764c8e3fc9b].Cost
so I manually put 2 inputs on the view with the name attributes
invoiceItems[firstOne].Description
invoiceItems[firstOne].Cost
but it didn't show up in the model on the controller after submitting the form.
I can't just insert one the BeginCollectionItem way when the view loads because the initial item has to be displayed differently.
Not exactly answer to your question, but I hope it will solve your problem.
Instead of changing the name in the view, you may try changing the model. Add a boolean property IsFirst. I believe you know in the controller(or wherever the model is being instantiated) which one is first. Set the first items IsFirst to true.
I figured it out. I was on the right track with manually putting in the stuff that BeginCollectionItem did, I was just missing a part. You need another hidden input that tells the binding what the index you're using is.
So the following works perfectly
<input type="hidden" name="invoiceItems.index" autocomplete="off" value="firstOne" />
<input type="text" placeholder = "ex. Labour" id="invoiceItems_firstOne__Description" name="invoiceItems[firstOne].Description" />
<input type="text" placeholder = "ex. $15" id="invoiceItems_firstOne__Cost" name="invoiceItems[firstOne].Cost" />
I just added the top hidden input to what I had before and it's all good.

Misbehaving Asp.net MVC helper methods (ie: Html.TextBox() and Html.Hidden())

I've been trying to debug an issue and I pinned pointed it down to this scenario:
When the statement Html.TextBox("ID", "What the heck..") is executed, I expect it to render:
<input id="ID" name="ID" type="text" value="What the heck.." />
But I get a Guid as its TextBox value such as so:
<input id="ID" name="ID" type="text" value="2e369d2c-071d-4733-8382-cc9e77d0b912" />
Why is Asp.net MVC outputting Guids? I'm not overriding asp.net mvc's framework methods. Please refer to the screenshot.
Update:
Here's another screenshot using Html.Hidden() instead of Html.TextBox(). I couldn't use Html.HiddenFor() directly into the Watch window because HiddenFor() uses lambdas.
#Eric Petroelje and #TLS: You two are correct. TextBox() and Hidden() is retrieving ID's value from the POST variables and not from the current Model or the function's value parameter. Though, I've expected different from HiddenFor() and TextBoxFor(). I expected it to get its value from the POST'ed variables only if it cant get it from the current Model. How can I achieve this?
Maybe you have a POST variable named ID that is a GUID? If that's the case, the HTML Helper method will use that POST value. If no POST value is present, it will fall back to the value in the model.
You are correct that Html.TextBox("ID", "What the heck..") is expected to output the attribute values that you give in your first example; however, if you are using the Html.TextboxFor method, then you're using a MVC Helper that dynamically loads the value of the ID property and places that into the value attribute in the HTML. When you use the Html.TextboxFor method, your second example is the expected HTML output if your ID property is a Guid.

Resources