views:

48

answers:

3

Alright, I'm trying to pass a Dictionary, where key = int, and value = Prototype into my view.

Prototype:

public class Prototype     
{
    public string Value { get; set; }
    public string PropertyName { get; set; }
    public Options Type { get; set; }
}

After the Dictionary has been passed into my view I'm doing a foreach loop to render each of the KeyValuePair:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Dictionary<System.Int32,MvcApplication1.Models.Prototype>>" %>
<%@ Import Namespace="SecuredFormExample.Code" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Index</title>
</head>
<body>
    <div>

    <% Html.BeginForm("Save", "Products", FormMethod.Post); %>

    <% foreach (KeyValuePair<int, Prototype> p in Model)
       { %>
       <%: Html.Label(p.Value.PropertyName) %>
       <%: Html.TextBox("Value") %>
       <% } %>
    <p><input type="submit" value="submit" /></p>

    <% Html.EndForm(); %>

    </div>
</body>
</html>

Now is the question, is it possible to pass the other values in the KeyValuePair value part back to the action aswell, or do I need to throw them all into hidden fields?

A: 

If you want to get the values back into the action you are posting to you need to send them along the request. Using hidden fields is one way of doing it. Another way is to only send an identifier which will allow you to fetch those values from a repository in the controller action you are posting to, the same way you are doing it in the controller action which renders the form.

If you are worried about users tampering with hidden fields you could serialize and encrypt entire objects using the Html.Serialize.


UPDATE:

Here's an example to expand on my second proposition which was to use an id:

<% Html.BeginForm("Save", "Products", FormMethod.Post) { %>
    <%: Html.Hidden("id", "PUT AN ID HERE WHICH IDENTIFIES THE ITEM")
    <% foreach (KeyValuePair<int, Prototype> p in Model) { %>
       <%: Html.Label(p.Value.PropertyName) %>
       <%: Html.TextBox("Value") %>
    <% } %>
    <p><input type="submit" value="submit" /></p>
<% } %>

and in your controller action:

public ActionResult Save(string id, ....) 
{
    var data = SomeRepository.FetchData(id);
    ...
}
Darin Dimitrov
Hidden fields seems to risci due to the value can be changed by the user.. I have read about encrypted hidden fields along with salts.. but both examples I have found is broken and I'm not that good I can code my own HtmlHelper for that yet.. so what would another way doing it be?
ebb
I'm not sure I know what you mean by only sending the Identifier, possible you could give an example please?
ebb
The Serialize extension you mentioned earlier is a part of ASP.NET MVC 2 futures assembly - does that mean its "under development" or can it be used here and now?
ebb
It can be used, it's just not part of the core build. I've used it in multiple projects without any issues. Many useful extensions that were in the Futures assembly were included in the ASP.NET MVC 2 build.
Darin Dimitrov
Great! - I have now included Microsoft.Web.Mvc in my project but still not able to use any of its classes, helpers etc. ?
ebb
You need to add the proper namespace in your web.config file: `<add namespace="Microsoft.Web.Mvc"/>` so that the helper methods are brought into scope.
Darin Dimitrov
Just tried that.. its the same.. cant access the classes inside the namespace.
ebb
Try rebuilding and running the project. It might be a bug with the Intellisense not showing them. You could also try using the Import directive on the top of the view: `<%@ Import Namespace="Microsoft.Web.Mvc" %>`.
Darin Dimitrov
I have tried rebuilding/running the project and the Import directive.. still no luck.
ebb
@user407674, then you have some other problem which cannot be figured out from the information you provided. Are you sure you referenced the `Microsoft.Web.Mvc` assembly? Can you see the classes inside from with in a controller for example?
Darin Dimitrov
Yes, If I do Microsoft.Web.Mvc. in my controller I can see all the classes, however I cant just CLASSHERE even when I have "using Microsoft.Web.Mvc"
ebb
@user407674, what error message are you getting when you put the following in your view: `<%= Html.Serialize("products", Model) %>`?
Darin Dimitrov
Error 1 'System.Web.Mvc.HtmlHelper<System.Collections.Generic.Dictionary<int,MvcApplication1.Models.Prototype>>' does not contain a definition for 'Serialize' and no extension method 'Serialize' accepting a first argument of type 'System.Web.Mvc.HtmlHelper<System.Collections.Generic.Dictionary<int,MvcApplication1.Models.Prototype>>' could be found (are you missing a using directive or an assembly reference?) c:\Users\ebb\Documents\My Dropbox\xmcube\MvcApplication1\MvcApplication1\Views\Products\Index.aspx 17 17 MvcApplication1
ebb
Could you upload your project somewhere so that I can take a look at what might be wrong?
Darin Dimitrov
hmm.. changed from my desktop computer to my laptop and now it works..
ebb
But thank you very much for your help, I really appreciate it ;=)
ebb
Hey again :) - Do you know if its possible to only serialize the ID in the model? When I try to serialize the whole model it just returns null.. if I dont do Deserialize then it returns with the data, but where the id still are encrypted. Short: Can I only serialize one property in the model instead of the whole model?
ebb
Doh.. just answered my own question.. have to add [Serializable] above the class I want to use.
ebb
A: 

Just seen your update, your options are limited only by HTML and Browser capabilities, so things like Hidden fields seem natural here. Other choices like scripting could be made to work but are way more complex than the automatic behaviour of hidden fields.

MVC Futures shows where the general path. It has a bunch of HtmlHelper extensions to generate hidden fields and encode object state into those fields. Of course you may have extra requirements like tamper-security etc. that you could layer on top of these methods.

http://aspnet.codeplex.com/SourceControl/changeset/view/55373#338518

  • BinaryHtmlExtensions.cs
  • ExpressionInputExtensions.cs

Effectively these'd be treated like old school ViewState, where you'd reconstitute model state in your controller by decoding these fields.

stephbu
A: 

The options for passing non-visible values from one page to the next in ASP.NET MVC are:-

1) Hidden fields (encrypted or otherwise)

2) Cookies (hidden or otherwise)

3) Url parameters (encoded or otherwise, limited size)

4) Session state (stuffing this with big objects is generally not a good idea)

5) TempData (like session state but lasts just one 'cycle')

6) Database (pass just a key so you can retrieve the data on the next page)

For this example, if your data isn't too large and you aren't on a load balanced Web Farm, I'd recommend TempData as the easiest solution. (If you are on a load balanced farm you can still do it but you may need to change how session state is handled).

Hightechrider