0

I have an object class Tag {string Key; string Text;} and an object Record that is bind to a storage table.

class Record { [...Id & other properties...]
    public string Name { get; set; } // "FirstRecord"
    public string Tags { get; set; } // "3,4,9"
}

Updating the Name does not present a problem. But I have some difficulties with the Tags... As you can see the Tags property is the CSV of int keys (say {1:".net",2:"java",3:"perl" ...}).

In the Record's Edit View I build a dictionary with all available Tags:

Dictionary<string, string> tags = ViewData["tags"] as Dictionary<string, string>;
[...]
<div class="form-group">
    <label class="col-md-2 control-label">Tags</label>
    <div class="col-md-10">
        @foreach (var tag in tags)
        {
            <div class="checkbox-inline">
                <label for="tag_@tag.Key">
                    <input type="checkbox" id="tag_@tag.Key" value="@tag.Key" />
                    @tag.Value
                </label>
            </div>
        }
    </div>
</div>

And finally I have the Edit Post controller, like this

// POST: Records/Edit/5
[HttpPost, ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(string id, [Bind("Id,Name")] Record record)
{
    if (id != record.Id) {
        return NotFound();
    }

    if (ModelState.IsValid) {
        try {
            await repository.UpdateTableEntityAsync(record);
        }
        catch (Exception) { [...] }

        return RedirectToAction("Index");
    }
    return View(record);
}

So, I am confused if I should Bind Tags, like [Bind("Id,Name,Tags")], because that value should be taken from all the checked check-boxes values, then concatenated as CSV to be ready to be updated in the storage...

serge
  • 13,940
  • 35
  • 121
  • 205
  • Storing your tags as a csv is bad practice - refer [Is storing a delimited list in a database column really that bad?](https://stackoverflow.com/questions/3653462/is-storing-a-delimited-list-in-a-database-column-really-that-bad) - and you should have a separate table with a navigation property. But as far as the view is concerned, you should be creating view models for your view, similar to [this answer](https://stackoverflow.com/questions/29542107/pass-list-of-checkboxes-into-view-and-pull-out-ienumerable/29554416#29554416) –  Jul 25 '17 at 12:57

1 Answers1

0

If you want to bind the checkbox values to a string, you could get all the values of checkbox and set the value of model manually. Code below is for your reference.

In view, add a name property for checkbox.

<input type="checkbox" name="tag_@tag.Key" id="tag_@tag.Key" value="@tag.Key" />

In action, we could get all the values of checkbox using Request.Form.

[HttpPost, ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(string id, [Bind("Id,Name")] Record record)
{
    if (id != record.Id)
    {
        return NotFound();
    }

    record.Tags = "";
    foreach (var key in Request.Form.AllKeys)
    {
        if (key.StartsWith("tag_"))
        {
            record.Tags += Request.Form[key] + ",";
        }
    }
    if (record.Tags.Length > 0)
    {
        record.Tags = record.Tags.Remove(record.Tags.Length - 1, 1);
    }

    if (ModelState.IsValid)
    {
        try
        {
            await repository.UpdateTableEntityAsync(record);
        }
        catch (Exception)
        {
        }

        return RedirectToAction("Index");
    }
    return View(record);
}
Amor
  • 8,325
  • 2
  • 19
  • 21