views:

74

answers:

1

Hello there! I'm trying to use the new Html helper extension Serialize() from the furthure assembly..

If you take a look at:

View

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<List<MvcApplication2.Models.ProductViewBinding>>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<%@ Import Namespace="Microsoft.Web.Mvc" %>>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Index</title>
</head>
<body>
    <div>
    <% using (Html.BeginForm("Index", "Products", FormMethod.Post))
       { %>
       <% int codeIndex = 0;
           foreach (var item in Model)
          { %>
          <%: Html.TextBox("Encryption[" + codeIndex + "].Value") %>
          <%: Html.Serialize("Encryption[" + codeIndex + "].ID", item.ID) %>
          <% codeIndex++; 
        } %>
       <%: Html.SubmitButton("Click meh!") %>
    <% } %>
    </div>
</body>
</html>

Model

[Serializable] 
public class ProductViewBinding
{

    public object ID { get; set; }

    [NonSerialized]
    public object _value;
    public object Value 
    { 
        get { return this._value; } 
        set { this._value = value; } 
    }

}

Controller

[HttpPost]
public ActionResult Index([Deserialize] List<ProductViewBinding> Encryption)
{
    return View("Index", Encryption);
}

It returns null when posted... but if I remove the [Deserialize] attribute it returns as it should but with the ID still encrypted... Any suggestions for what I might be doing wrong?

A: 

I think you are missing the point of how the Serialize helper is supposed to work. You pass it an entire object graph which is serialized and stored in a hidden field that you could get back in a controller action using the [Deserialize] attribute. You cannot have half of your object serialized and the other half not.


UPDATE:

After seeing your comment here's a workaround:

Model:

public class ProductViewBinding
{
    public string ID { get; set; }
    public string Value { get; set; }
}

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new[] 
        {
            new ProductViewBinding { ID = "1", Value = "value 1" }, 
            new ProductViewBinding { ID = "2", Value = "value 2" }, 
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(
        [Deserialize(SerializationMode.Encrypted)]string[] ids,
        string[] values
    )
    {
        IEnumerable<ProductViewBinding> model = values.Zip(
            ids, (id, value) => new ProductViewBinding { ID = id, Value = value }
        );
        return View("Index", model);
    }
}

View:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<SomeNs.Models.ProductViewBinding[]>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<%@ Import Namespace="Microsoft.Web.Mvc" %>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Index</title>
</head>
<body>
    <% using (Html.BeginForm()) { %>
        <%: Html.Serialize("ids", Model.Select(x => x.ID).ToArray(), SerializationMode.Encrypted) %>
        <%for (int i = 0; i < Model.Length; i++) { %>
            <%: Html.TextBox("Values[" + i + "]", Model[i].Value) %>
        <% } %>
        <%: Html.SubmitButton("Click meh!") %>
    <% } %>
</body>
</html>

Notice the SerializationMode.Encrypted flag which is used if you want to achieve encryption, otherwise the user can tamper with the values.

Darin Dimitrov
I see.. But what would be the right way to Encrypt a key into a hidden field thats used to identifie the textbox when its a List<>? The thing I was trying to do would be ideal if it worked.. because I only need the ID field to be serialized, not the textbox (Value)...
ebb
@user407674, updated post to suggest a workaround.
Darin Dimitrov
I'll try it out and return with the result, thanks :)
ebb
Works great! - However users can still tamper with the values?
ebb
No, they can't tamper with the IDS because they are encrypted. If someone tampers with the values you will get either null in the controller action or exception but a user won't be able to modify a value.
Darin Dimitrov
If I edit the value of the generated hidden field for "ids" it returns "invalid length for a base-64 char array", and if I just copy another Serialize field' value to the "ids" value then it's accepted?
ebb
Where do you take this other value that's accepted from?
Darin Dimitrov
I have 2 Html.Serialize() on my site.. both are defined as strings... public ActionResult Order([Deserialize(SerializationMode.EncryptedAndSigned)] string[] ids,[Deserialize(SerializationMode.EncryptedAndSigned)] string[] pnames, string[] values) - So if I take the value from "pnames" and give it to "ids" it accepted.. - Would it be best to try to combine them into one to avoid such a thing?
ebb
Yes you should combine them into one.
Darin Dimitrov
I have just noticed a problem of same kind.. I have 2 pages -> Order(enter personal info etc.) and a confirm page. If I copy the value in the serialized hidden field from the Order page to Confirm page' hidden field, its accepted?
ebb