1

I have the following code. I'd like to do away with ContactIdsString, but I don't then know how to send the int[] in JavaScript to an IEnumerable in C#. Is there any way?

Html:

@model MyNamespace.Models.MassMailViewModel
@section scripts
{
    @Scripts.Render("~/bundles/mass-mail")
    <script>
        var contactIdsName = '@nameof(MassMailViewModel.ContactIdsString)'
    </script>
}

@using (Html.BeginForm(nameof(MassMailController.SendMail), "MassMail", FormMethod.Post, new { id = "massMailForm" }))
{
    @(Html.Kendo().Button()
        .Name("massMailButton")
        .Content("Send")
        .HtmlAttributes(new { type = "submit" })
    )

    @Html.HiddenFor(m => m.ContactIdsString)

    ...bunch of code for contact-mass-mail-grid...
}

JavaScript:

window.jQuery(function () {
    window.jQuery("#massMailForm").submit(function () {
        var ids = $('#contact-mass-mail-grid').data('kendoGrid').selectedKeyNames();
        var idsJson = JSON.stringify(ids);

        var hiddenField = $('#' + window.contactIdsName);
        hiddenField.val(idsJson);
    });
});

View Model:

public class MassMailViewModel
{
    public string ContactIdsString { get; set; }//TODO I'd like to not have to do this.
    public IEnumerable<int> ContactIds => JsonConvert.DeserializeObject<IEnumerable<int>>(ContactIdsString);
}

Controller:

public ActionResult SendMail(MassMailViewModel vm)
{
    ...
}
Sarov
  • 545
  • 6
  • 17

3 Answers3

0

It looks like you are stopping the value from being posted back in your javascript here:

window.jQuery("#massMailForm").submit

Since you have the ContactIdsString data hidden within the form here:

@Html.HiddenFor(m => m.ContactIdsString)

Why not just let the form submit by removing the submit event handler?

If you are not wanting to do that you would have to submit the data via an ajax call.
Look here for more ajax info https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX

Jake Steffen
  • 415
  • 2
  • 11
0

I'm not actually sure you can accomplish what you want without changing your HTML, and I don't think you show enough of your HTML to know really what would need to be changed. The hidden field is just an input, so you really only have one value you can store in it. I'm not sure the razer engine allows you to go to/from an array in a single input.

But, what you could do low impact is create a new getter and leave the ContactIdsString.

    public class MassMailViewModel
{
    public string ContactIdsString { get; set; }//TODO I'd like to not have to do this.
    public IEnumerable<int> ContactIds => this.ContactIdsString.Split(',').Select(n => int.Parse(n));
}

If you truly wanted to get rid of it entirely you'd have to follow the link for what @Kenneth K. suggests

Neil.Work
  • 985
  • 7
  • 9
0

I think you have a slight misunderstanding of the way that IEnumerable works. IEnumerable is for exposing an enumerator that will act on a set of materialized data. In this case, the data being sent to the server from the client is materialized, so there is no need to attempt to define it with an IEnumerable.

The model binder for ASP.NET MVC will attempt to initialize the values sent though, so just like IEnumerable<int> numbers = new int[]{1,2,3}; will work, so will accepting an array of integers into that IEnumerable.

All you need to do is follow the process of posting an array of integers to the server, which is why this question was closed as a duplicate of a question seeking that answer.

Travis J
  • 81,153
  • 41
  • 202
  • 273
  • Okay, int[] is acceptable. When I change the type of ContactIdsString from string to int[], though, it's now not receiving anything (just gets null). – Sarov May 24 '19 at 19:40