Asp Mvc one way model property, i.e. from client only - asp.net-mvc

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)

Related

Post a collection of HttpPostedFileBase objects each having an additional value

I have an MVC 5 project with a form where the user can select multiple files to upload. However each file needs to have an additional integer value indicating its type. How do I implement this so the post method receives the collection of HttpPostedFileBase objects, along with each having the type value?
It will "just work", as long as your POSTed data is in the right format. The MVC model binder should just hook things up. If you've already gotten your controller action to receive an array of HttpPostedFileBase objects, you should just be able to have another argument to your action that is the array of integers `int[] fileTypes'. In your form, you will need input elements that contain those integers, with NAME attributes that allow the MVC model binder to bind the collection properly, which usually means you'd have input elements like this on your page:
<input type="hidden" value="3" name="fileTypes[0]" />
<input type="hidden" value="5" name="fileTypes[1]" />
With something like that you'd have a controller action that looked like
public ActionResult UploadMultipleFiles(HttpPostedFileBase[] uploadedFiles, int[] fileTypes)
The model binder will actually take care of hooking the input arguments up for you, as long as they were named properly on the HTML form.
If you are doing your upload via AJAX POST, the same still holds, you just have to make sure that you put the fileTypes values in as form variables with the right key names for collection binding.

Dynamic Form in ASP.NET MVC3 Razor

I have a small problem.
I want to have dropdown list with some objects. After clicking on one I want to add it to list with textfield for naming it. I don't want to limit quantity of this fields. I want to receive in controller ID (stored in dropdown list) and name (given by user) for each selected item. How can I do it?
I was thinking about storing it in some fields as a text, and parsing in cotroller but I think it's not elegant.
EDIT.
Ok, Thansk for your help, but it's not working for me correctly.
I generate html like this:
<input type="hidden" value="96" name="Inputs[0].Key">
<input type="text" name="Inputs[0].Value">
In my controller I'm receiving this dictionary. The problem is that quantity of elements is correct, but all values are null. What is wrong here?
The best way to go about this is by using array-style model binding.
So, for each element you wish to name you create a hidden field to store the drop down value plus a text field to store the user-given name. You name them as follows:
<input type="hidden" name="element[0].Key" /><input type="text" name="name[0].Value" />
increasing the index value each time. This is easily achieved with a bit of JavaScript. You then create an action method which takes a KeyValuePair<string, string>[] as a parameter. You will then be able to parse through your values no problem with a loop or LINQ expression.
Use IEnumerable<KeyPairValue<string,string>> MySelectedItem = new List<KeyPairValue<string,string>>(); on model, and when adding it to the list, name it like an array:
MySelectedItem[1].Key, MySelectedItem[1].Value, MySelectedItem[2].Key...
(I haven't tested this, but it should work)
Edit: check out this blog post with better explanation on how to do it: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

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.

Enforcing different validation rules on a form with different submit buttons

I have a view with a form that is mapped to a ViewModel. I have 2 submit buttons in the form. When the form is submitted using 1 of the buttons, some of the fields in the form are going to be empty - is it possible to avoid validating the empty fields when the form is submitted using this 1 button? (Using the other button I would like to keep the usual validation rules).
Unfortunately I cannot seperate the fields that I expect to be empty into a seperate ViewModel because both models would have a common field that always needs to be populated.
Any ideas on this? Any help would be much appreciated.
Many thanks.
James
It is possible, but
You will not be able to use clients-side validation
You will not be able to use data annotation attributes like Required etc and you probably need your own validation (or as option you may mark only properties are required in both cases and validate other properties manually)
You need to set different values for name attributes of your submits
<input type="submit" name="first-submit" value="First action" />
<input type="submit" name="second-submit" value="Second action" />
Then you may declare parameter of type FormCollection in your action method. Depends on which button was pressed it will contain first-submit key or second-submit key. Now you can alter your validation logic depends on this.

ASP.NET MVC 3 and HTML Helper Extensions

I am trying to work out whether I am misunderstanding something about ASP.NET MVC or whether I have found some sort of bug in ASP.NET MVC Beta 3. I am having a problem with a PartialView picking up the wrong model when using HTML Helper extensions
My controller code looks like this:
public ActionResult EditGeneral(MapGeneralViewModel vm)
{
var query = MapGeneralViewModel.ToModel(vm, svcMaps);
return PartialView("General", MapGeneralViewModel.FromModel(query));
}
In the case of this being an insert, the property vm.Id starts out as -1 and after the call to MapGeneralViewModel.ToModel it has been persisted the database and query.Id has a proper value.
The call to MapSettingsViewModel.FromModel returns a new viewmodel and I have checked that the Id property correct contains the newly created id value.
The relevant bits of the view look like:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<AdminWebRole.Models.Map.MapGeneralViewModel>" %>
<%: Model.Id %>
<%= Html.Hidden("IdTest", Model.Id) %>
<%= Html.HiddenFor(model => model.Id) %>
If I put a breakpoint in the view, Model.Id is correctly set to the right value.
The actual output of the controller (when Model.Id == 70) looks like this:
70
<input id="IdTest" name="IdTest" type="hidden" value="-1" />
<input id="Id" name="Id" type="hidden" value="-1" />
So the value output without using the HTML helpers is correct, but the values output by the helpers somehow is picking up the viewmodel that was passed into the controller !
I have no idea how this is happening. I have tried various things:
Using View() rather than PartialView()
assigning the results of MapGeneralViewModel.FromModel() to vm and then passing vm to the view
using <%: and <%=
setting vm to null (the old view model somehow still gets used)
changing the value of the incoming id to 0 (results in 0 being output in the view instead of -1)
the problem isn't specific to properties called "Id", I have also tested other fields with the same result
Am I confused over how this is supposed to work or have I hit a beta bug ? If it makes any difference, this is running inside my local Azure runtime on a Win7 64 bit machine.
There is no way that MVC is just picking up a variable that you haven't explicitly passed to your view or have hanging around in Session or TempData.
Since you're setting that Id to -1 I'm start there for problems.
The other possibility is that -1 is hanging around in your ModelState someplace. The HTML helpers look to ModelState first before deciding to use any values you pass in.
I have just come across a similar issue in a partial view that I use for displaying the items in an order.
I was using the following to render a hidden input.
#Html.Hidden("salesorderlineid", orderLine.SalesOrderLineID)
This works fine until I delete an item, when the ID of the wrong (deleted) item is used. I double-checked the model, this was correct and rendered correctly in other usages on the same view.
I coded the hidden input directly as html and it works fine - looks like an MVC3 bug perhaps?
<input type="hidden" name="salesorderlineid" value="#orderLine.SalesOrderLineID"/>

Resources