2

I'm using MVC 3 and Razor.

I have a page where you can create a Vendor. On the front-end, a vendor's page has 3 things: A name, a description (HTML), and multiple tabs that contain HTML. My client wants the tabs to be dynamic, they want to be able to add/edit/delete tabs and content when they add a vendor.

So here's my database design:

Vendors
-------------------
VendorID (PK)
Name
Description

VendorTabs
-------------------
VendorTabID (PK)
VendorID (FK)
Title
Content

Here's my view model:

public class VendorViewModel
{
    [ScaffoldColumn(false)]
    public int VendorId { get; set; }

    public string Name { get; set; }

    [AllowHtml]
    public string Description { get; set; }
}

And my controller post method:

[HttpPost]
public ActionResult Create(VendorViewModel viewModel, string[] tabTitles, string[] tabContent)
{
    var vendor = new Vendor();
    vendor.Name = viewModel.Name;
    vendor.Description = viewModel.Description;

    if (ModelState.IsValid)
    {
        for (int i = 0; i < tabTitles.Length; i++)
        {
            vendor.VendorTabs.Add(new VendorTab
            {
                VendorID = vendor.VendorID,
                Title = tabTitles[i],
                Content = tabContent[0]
            });
        }

        _vendorsRepository.SaveVendor(vendor);

        return RedirectToAction("Index");
    }

    return View(viewModel);     // validation error, so redisplay same view
}

In my view, I have functionality to dynamically add/remove fields for a tab title and a tab description. They are passed to the controller through the arrays tabTitles and tabContent. But when I post the form with HTML in the dynamic tab content, I get the following error:

A potentially dangerous Request.Form value was detected from the client

I ran into this problem before, with the Description field for my Vendor. After some research, I saw that I can add the AllowHtml annotation.

How can I apply the same functionality to my dynamic content?

Steven
  • 18,761
  • 70
  • 194
  • 296
  • possible duplicate of [A potentially dangerous Request.Form value was detected from the client](http://stackoverflow.com/questions/81991/a-potentially-dangerous-request-form-value-was-detected-from-the-client) – Martin Aug 28 '11 at 03:11

2 Answers2

9

instead of arrays tabTitle and tabContent, structure your viewmodel in a way that you can put the AllowHtmlAttribute on each individual property that could take in user content, and then just include a List of these in the Model you are binding the View to

public class TabViewModel
{
    [AllowHtml]
    public string Title { get; set; }

    [AllowHtml]
    public string Content { get; set; }
}
kenwarner
  • 28,650
  • 28
  • 130
  • 173
  • 1
    Okay, so I have `IEnumerable Tabs` as a property of `VendorViewModel` now. If I'm not using the arrays `tabTitle` and `tabContent`, how can I associate my dynamic content with `Tabs`? – Steven Aug 28 '11 at 03:25
  • ha. I added an answer and realized it basically was the exact same as yours (I dont like reading others before mine to ensure mine is original) +1 : ) – Adam Tuliper Aug 28 '11 at 03:53
  • Create a property in your TabViewModel specifically for these lists as qntmfred said so you aren't relying on dynamic binding, otherwise I think you need ValidateRequest(false) which is not recommended in general. – Adam Tuliper Aug 28 '11 at 03:54
  • The fields should be named like Tabs[0].Title etc. The Tabs property should probably be of type TabViewModel[]. – ulu Aug 28 '11 at 12:11
0

How about make [AllowHtml] string[] TabContent {get;set;} a property of the Model?

ulu
  • 5,872
  • 4
  • 42
  • 51