1

I have a form where either at least one checkbox must be checked OR a textbox is filled in.

I have a ViewModel that populates the CheckboxList and takes the selected values plus the textbox (other) value when required to a SelectedWasteTypes property within the ViewModel. I think my problem is I can't validate against this property as there is no form element on the view that directly relates to it. I've very new to MVC and this one has stumped me.

From the ViewModel

public List<tblWasteTypeWeb> WasteTypeWebs { get; set; }
public string WasteTypeWebOther { get; set; }
public string SelectedWasteTypes { get; set; }

View (segment)

@using (Html.BeginForm("OrderComplete", "Home"))
{
    //Lots of other form elements

    @for (var i = 0; i < Model.WasteTypeWebs.Count; i++)
        {
            var wt = Model.WasteTypeWebs[i];
            @Html.LabelFor(x => x.WasteTypeWebs[i].WasteTypeWeb, wt.WasteTypeWeb)
            @Html.HiddenFor(x => x.WasteTypeWebs[i].WasteTypeWebId)
            @Html.HiddenFor(x => x.WasteTypeWebs[i].WasteTypeWeb)
            @Html.CheckBoxFor(x => x.WasteTypeWebs[i].WasteTypeWebCb)
        }
        <br />
        <span>
            @Html.Label("Other")
            @Html.TextBoxFor(x => x.WasteTypeWebOther, new { @class = "form-control input-sm" })
        </span>

    //More form elements

    <input type="submit" value="submit" />
}

Controller Logic (if you can call it that)

[HttpPost]
public ActionResult OrderComplete(OrderViewModel model)
{
    var sb = new StringBuilder();
    if (model.WasteTypeWebs.Count(x => x.WasteTypeWebCb) != 0)
    {
        foreach (var cb in model.WasteTypeWebs)
        {
            if (cb.WasteTypeWebCb)
            {
                sb.Append(cb.WasteTypeWeb + ", ");
            }
        }
        sb.Remove(sb.ToString().LastIndexOf(",", StringComparison.Ordinal), 1);
    }

    model.SelectedWasteTypes = sb.ToString();

    if (!string.IsNullOrEmpty(model.WasteTypeWebOther))
    {
        if (!string.IsNullOrEmpty(model.SelectedWasteTypes))
        {
            model.SelectedWasteTypes = model.SelectedWasteTypes.TrimEnd() + ", " + model.WasteTypeWebOther;
        }
        else
        {
            model.SelectedWasteTypes = model.WasteTypeWebOther;
        }
    }
    return View(model);
}

I very much feel I'm up a certain creek... I've thought about using JQuery, but ideally I'd like server side validation to be sure this info is captured (its a legal requirement). However, if this can only be achieved client side, I will live with it.

Any suggestions?

ComfortablyNumb
  • 1,448
  • 10
  • 37
  • 64

2 Answers2

2

Take a look at the MVC Foolproof Validation Library. It has validation attributes for what you are trying to accomplish: [RequiredIfEmpty] and [RequiredIfNotEmpty]. You can also take a look at my previous SO answer about Conditional Validation.

Community
  • 1
  • 1
viperguynaz
  • 12,044
  • 4
  • 30
  • 41
  • Thanks for that. I'm not sure what I'm supposed to validate against. The checkboxlist is from a in the ViewModel and the final property is not actually represented within the form but is added to the viewModel as a concat between the checkboxes checked and the textbox. – ComfortablyNumb Mar 03 '15 at 15:16
0

I would suggest you to implement IValidatableObject in your ViewModel. Inside Validate( ValidationContext validationContext) method you can check weather your conditions are met. For example:

if(string.IsNullOrWhiteSpace(WasteTypeWebOther))
    yield return new ValidationResult("Your validation error here.");
vortex
  • 1,048
  • 1
  • 10
  • 17
  • When I add validation,the ViewModel it seems to validate on pageLoad not when I click submit. Am I doing something wrong? However, I've used you suggestion else where to good effect! – ComfortablyNumb Mar 03 '15 at 15:14