2

I have created a MVC 5 application that generates dynamic controls. The formcollection is null on postback. I have enclosed the form in formtag. Not sure what the problem is

Below is the main form. Clciking on submit doesnt post back formcollection

Actual UI

enter image description here

View containing the menu items

@model IEnumerable<CC.GRP.BluePrismMenu.Models.BluePrismRequestCustomer>
@using Kendo.Mvc.UI;
@using (Html.BeginForm("MenuResult", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @*@Html.AntiForgeryToken()*@
    <div class="sidebar-nav k-content">
        @(Html.Kendo().Menu()
            .Name("nav")
            .BindTo(Model, mappings => {
                mappings.For<CC.GRP.BluePrismMenu.Models.BluePrismRequestCustomer>
            (binding => binding
            .ItemDataBound((item, requestCustomer) =>  {
                if (requestCustomer.Active == true) {
                    item.Text = requestCustomer.CustomerDisplayName;
                }
            })
            .Children(requestCustomer => requestCustomer.BluePrismRequestTypes));
                mappings.For<CC.GRP.BluePrismMenu.Models.BluePrismRequestType>
                    (binding => binding
                    .ItemDataBound((item, requestType) => {
                        if (requestType.CustomerID > 0) {
                            if (requestType.Active == true) {
                                item.Text = Convert.ToString(requestType.RequestTypeID) + "," + requestType.RequestTypeValue;
                            }
                        }
                    }));
            })
                .Orientation(MenuOrientation.Vertical)
                .Events(e => e.Select("menuItemSelect"))
        )
    </div>
}
<script type="text/javascript">
    var Cid = "";

    function menuItemSelect(e) {
        var Cname = "";
        var MSelect = $(e.item).children(".k-link").text();
        var fields = MSelect.split(",");
        if (fields[0] != null) {
            Cid = fields[0];
            Cname = fields[1];
        }
        $("#article").load("Home/MenuResult", { requestTypeID: Cid });
    }

    //function onClickPost() {
    //        $("#article").load("Home/Edit", { requestTypeID: Cid });
    //}

</script>
    <div id="article" class="article-div">
    </div>

View containing the dynamic controls

   @model IEnumerable<CC.GRP.BluePrismMenu.Models.BluePrismRequestTypeConfig>
@{
    ViewBag.Title = "Blue Prism Submit Edit";
}
<hgroup class="title">
    <h1>@ViewBag.Title.</h1>
    <h2>@ViewBag.Message</h2>
</hgroup>
<BR />


@using (Html.BeginForm("Edit", "Home"))
    {
    <script type="text/javascript">
        function onClickPost() {
             $("#article").load("Home/Edit", {requestTypeID: Cid});
    }
    </script>



    @Html.AntiForgeryToken()
    <div class="form-horizontal" id="myform">
        <div class="row">
            <h4>Send Request @ViewBag.Header</h4>
        </div>
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <fieldset>
            <legend>Edit</legend>
            @foreach (var item in Model)
                {
                    switch (item.FieldType)
                    {
                        case "TEXT":

                        <div class="form-group row">
                            @Html.Label(item.FieldLable, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @(Html.Kendo().TextBox().Name(item.FieldLable.Replace(" ", "-")))

                                @Html.ValidationMessage(item.FieldLable.Replace(" ", "-"), new { @class = "text-danger" })
                            </div>
                        </div>

                        break;
                    case "DATE":

                        <div class="form-group row">
                            @Html.Label(item.FieldLable, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @(Html.Kendo().DatePicker().Name(item.FieldLable.Replace(" ", "-")).Format("dd/MM/yyyy"))
                                @Html.ValidationMessage(item.FieldLable.Replace(" ", "-"), new { @class = "text-danger" })
                            </div>
                        </div>

                        break;
                    case "NUMBER":

                        <div class="form-group row">
                            @Html.Label(item.FieldLable, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">
                                @(Html.Kendo().NumericTextBox().Name(item.FieldLable.Replace(" ", "-")).Format("{0:n0}").Decimals(0))
                                @Html.ValidationMessage(item.FieldLable.Replace(" ", "-"), new { @class = "text-danger" })
                            </div>
                        </div>

                        break;
                }
            }
        </fieldset>
    </div>


    <br /><br />
    <div class="form-group row">
        <div class="col-md-offset-2 col-md-10">
            @(Html.Kendo().Button()
                .HtmlAttributes(new { type = "button" })
                .Name("textButton")
                .Icon("tick")
                .Content("Submit")
                .Events(ev => ev.Click("onClickPost"))
            )

            <a href="/CC.GRP.BluePrismMenu/" id="cancel">Clear</a>
            <script>jQuery(function () { jQuery("#cancel").kendoButton({ "icon": "cancel" }); });</script>
        </div>
    </div>
}

Controller

   [AcceptVerbs(HttpVerbs.Post)]
        //[ValidateAntiForgeryToken]
        public ActionResult Edit(int? RequestTypeID,  FormCollection fc)
        {
            ServiceReference1.ComputaCenterLoader1PortTypeClient Service = new ServiceReference1.ComputaCenterLoader1PortTypeClient();
            Service.ClientCredentials.UserName.UserName = ConfigurationManager.AppSettings.Get("userName");
            Service.ClientCredentials.UserName.Password = ConfigurationManager.AppSettings.Get("Password");

            //var bluePrismRequestTypeConfig = db.BluePrismRequestTypeConfigs.Where(o => o.RequestTypeID == RequestTypeID && o.Active == true).ToList();

            BluePrismRequestType bluePrismRequestType = db.BluePrismRequestTypes.Find(RequestTypeID);

            StringBuilder builder = new StringBuilder();
            int count;
            builder.Length = 0;
            count = 0;
            foreach (var key in fc.Keys)
            {
                if (key.ToString() != "__RequestVerificationToken")
                {
                    count = count + 1;
                    if (count == 1)
                    {
                        builder.Append(fc[key.ToString()]);
                    }
                    else
                    {
                        builder.Append("," + fc[key.ToString()]);
                    }
                }
            }
            try
            {
                Service.Loader("auto", bluePrismRequestType.RequestTypeValue.ToString(), builder.ToString());
                TempData["Status"] = "Send successfully";
            }
            catch (SoapException error)
            {
                TempData["Status"] = error.Detail.ToString();
            }
            catch (Exception e)
            {
                TempData["Status"] = e.InnerException.Message.ToString();
            }

            BluePrismTraceMessage bluePrismTraceMessage = new BluePrismTraceMessage();
            bluePrismTraceMessage.TraceTime = DateTime.Now;
            bluePrismTraceMessage.USERID = WindowsIdentity.GetCurrent().Name;
            bluePrismTraceMessage.Message = "RequestType:" + bluePrismRequestType.RequestTypeValue + ";variable:" + builder.ToString();
            bluePrismTraceMessage.ResponseXML = TempData["Status"].ToString();

            db.BluePrismTraceMessages.Add(bluePrismTraceMessage);
            db.SaveChanges();
            Service.Close();
            return RedirectToAction("Index");
        }
K Scandrett
  • 16,390
  • 4
  • 40
  • 65
Tom
  • 8,175
  • 41
  • 136
  • 267
  • AFAIK, `FormCollection` returns null on submit if no `name` attribute has been set on Kendo helpers (related to HTML behavior). Have you checked that `item.FieldLable` is not null or empty? If it still doesn't work, you need to try `for` loop instead of `foreach` with index array between control names. – Tetsuya Yamamoto May 03 '17 at 02:57
  • Could you suggest me a good example of doing it – Tom May 03 '17 at 07:09
  • I want to make sure that `item.FieldLable` which linked to `Name(item.FieldLable.Replace(" ", "-"))` (creating HTML `id` & `name` attribute) is not null/empty before proceeding, then you may examine `foreach` loop for generated input textboxes. Also for what reason you commented `[ValidateAntiForgeryToken]` there? – Tetsuya Yamamoto May 03 '17 at 07:14

1 Answers1

1

The main problem is your onClickPost() passes only one parameter - requestTypeID, so the parameter fc in the controller will always be null:

function onClickPost() {
   $("#article").load("Home/Edit", {requestTypeID: Cid});
}

I'd receive the dynamic form data as dictionary in the controller:

[HttpPost]
public ActionResult Edit(int? RequestTypeID, Dictionary<string, string> myDynamicData) {

  ViewData["Message"] = "Edit called, and ";

  foreach(string key in myDynamicData.Keys) {
    ViewData["Message"] += $ "{key} is {myDynamicData[key]}, ";
  }

  return View();
}

Then onClickPost() can serialize your dynamic form with:

function onClickPost() {

    function getFormData($form) { // from http://stackoverflow.com/a/11339012/1544886
        var unindexed_array = $form.serializeArray();
        var indexed_array = {};

        $.map(unindexed_array, function (n, i) {
            indexed_array[n['name']] = n['value'];
        });

        return indexed_array;
    }

    var $form = $(document.forms[0]);
    var data = getFormData($form);

    $("#article").load("/Home/Edit", { requestTypeID: Cid, myDynamicData: data });
}

(also note you'll likely want to include the leading forward slash in "/Home/Edit")

K Scandrett
  • 16,390
  • 4
  • 40
  • 65
  • As @TetsuyaYamamoto comments, you must make sure your form elements have a name and that they are unique, so that they serialize correctly. You can check the generated HTML to make sure that is the case. – K Scandrett May 07 '17 at 12:30