0

I am running to an issue with .net and MVC. I am trying to select a group of images that is being rendered on the webpage correctly, select a few images via a checkbox, and delete those images. However, the controller is null with no data so I cant do anything with it. Can someone steer me in the correct direction?

EditImages.cshtml

@model Images

@{
ViewBag.Title = "EditImages";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section CSS
{
<style>
    .Image {
        position: relative;
        float: left;
        margin-left: 10px;
        border-color: white;
        border-style: solid;
        border-spacing: 100px;
        margin-top: 10px;
        color: red;
    }

    .checkbox {
        position: relative;
    }
</style>
}
<h2>EditImages</h2>

@using (Html.BeginForm("DeleteImages", "Image", FormMethod.Post))
{
for (var i = 0; i < Model.ImageList.Count(); i++)
{
    var modellist = Model.ImageList.ToList();
    <div class="Image">            
        <p class="Image.Font">@Html.DisplayFor(m =>     modellist[i].FileName</p>
        <p>@Html.DisplayFor(m => modellist[i].FullImage.Width) x @Html.DisplayFor(m => modellist[i].FullImage.Height)</p>

        <img src="data:image/jpg;base64,@(Html.Raw(Convert.ToBase64String( modellist[i].ByteArray)))" height="225" width="400" />          
        <p>@Html.CheckBoxFor(m => modellist[i].isSelected, new {  id = modellist[i].id  })</p>
        <label>@modellist[i].id</label>            
    </div>
}

<p><input type="submit" id="delete" title="Delete1" value="Delete Images" /></p>
}

Controller - ImageController

    [HttpPost]
    public ActionResult DeleteImages(Images model)
    {
        //var temp = new Lobby_Monitor.Models.Images();
        //temp = model;

        string a = "";

        return View();
    }

Model - Images

 public class Images
{
    public int id { get; set; }
    public string FileName { get; set; }
    public string Extension { get; set; }

    public byte[] ByteArray { get; set; }

    public string UserId { get; set; }

    public string UserName { get; set; }

    public HttpPostedFileBase postedFile { get; set; }

    public string stream_id { get; set; }

    public Image FullImage { get; set; }

    public IEnumerable<DBImages> ImageList { get; set; }

    public Boolean isSelected { get; set; }

}

I''ve ran this through Fiddler to see what was being posted. There is data being posted. I believe with this test, I clicked the first 2 images.

Name                      Value
modellist[0].isSelected    true
modellist[0].isSelected    false
modellist[1].isSelected    true
modellist[1].isSelected    false
modellist[2].isSelected    false
modellist[3].isSelected    false
modellist[4].isSelected    false

enter image description here

Sample of Generated HTML

    <div class="Image">            
        <p class="Image.Font">Capture.PNG</p>
        <p>1667 x 866</p>

        <img src="image stuff" height="225" width="400" />


        <p><input data-val="true" data-val-required="The isSelected field is required." id="2" name="modellist[1].isSelected" type="checkbox" value="true" /><input name="modellist[1].isSelected" type="hidden" value="false" /></p>
        <label>2</label>
        <p><input type="submit" id="delete" title="Delete1" value="Delete Images" /></p>
    </div>
    <div class="Image">            
        <p class="Image.Font">tunein.png</p>
        <p>703 x 753</p>

        <img src="image stuff" height="225" width="400" />


        <p><input data-val="true" data-val-required="The isSelected field is required." id="3" name="modellist[2].isSelected" type="checkbox" value="true" /><input name="modellist[2].isSelected" type="hidden" value="false" /></p>
        <label>3</label>
        <p><input type="submit" id="delete" title="Delete1" value="Delete Images" /></p>
    </div>
    <div class="Image">            
        <p class="Image.Font">Qatar-Museum-1920x1080.jpg</p>
        <p>1920 x 1080</p>

        <img src="" height="225" width="400" />


        <p><input data-val="true" data-val-required="The isSelected field is required." id="4" name="modellist[3].isSelected" type="checkbox" value="true" /><input name="modellist[3].isSelected" type="hidden" value="false" /></p>
        <label>4</label>
        <p><input type="submit" id="delete" title="Delete1" value="Delete Images" /></p>
    </div>
    <div class="Image">            
        <p class="Image.Font">Brooklyn-College-1920x1080.jpg</p>
        <p>1920 x 1080</p>

        <img src="image info" height="225" width="400" />


        <p><input data-val="true" data-val-required="The isSelected field is required." id="5" name="modellist[4].isSelected" type="checkbox" value="true" /><input name="modellist[4].isSelected" type="hidden" value="false" /></p>
        <label>5</label>
        <p><input type="submit" id="delete" title="Delete1" value="Delete Images" /></p>
    </div>
<p><input type="submit" id="delete" title="Delete1" value="Delete Images" /></p>

gmalenko
  • 162
  • 4
  • 16
  • You need to send to the Controller only the Image Id? – Pedro Fernandes Filho May 31 '16 at 20:47
  • yea thats the only necessary part. But what am I missing. I guess this has to be a list of some type going to the controller – gmalenko May 31 '16 at 20:48
  • The Action need to receive an int array. – Pedro Fernandes Filho May 31 '16 at 20:54
  • Your controller signature needs to be an int array (as @PedroFernandesFilho noted). Right now that method is expecting a single Image object and it isn't getting one so it won't route you into that method. – nurdyguy May 31 '16 at 20:59
  • I understand what is saying. I'm an MVC noob really. I've changed the controller action to int[] model but still is getting null. I've ran this through Fiddler to see what is being posted. I'll update the question with the fidder data – gmalenko May 31 '16 at 21:11
  • Use List (unless you really have a reason to want just a simple array). Then put a debugger on the first line of the controller method and try to step into it. – nurdyguy May 31 '16 at 21:15
  • When you say " but still is getting null", what exactly do you mean? Do you mean you are debugging in the controller method but the parameter is null? Or do you mean something else is null? – nurdyguy May 31 '16 at 21:18
  • So i'm debugging, and the parameter to the controller is null – gmalenko May 31 '16 at 21:20
  • I've added a picture to the question to show what I'm seeing in Visual Studio – gmalenko May 31 '16 at 21:23
  • Can you post what the html for the form looks like? You have the razor but I'm curious to see exactly what you have in there after it is generated. – nurdyguy May 31 '16 at 21:25
  • I've added a sample of generated HTML to the question – gmalenko Jun 01 '16 at 14:06

1 Answers1

0

Remove var modellist = Model.ImageList.ToList(); from your loop and change it to (extra html removed for simplicity)

for (var i = 0; i < Model.ImageList.Count; i++)
{
    @Html.DisplayFor(m => m.ImageList[i].FileName
    @Html.DisplayFor(m => m.ImageList[i].FullImage.Width) x @Html.DisplayFor(m => m.ImageList[i].FullImage.Height)
    <img src="data:image/jpg;base64,@(Html.Raw(Convert.ToBase64String( Model.ImageList[i].ByteArray)))" height="225" width="400" />        
    @Html.CheckBoxFor(m => m.ImageList[i].isSelected)
    @Html.LabelFor(m => m.ImageList[i].isSelected, Model.ImageList[i].id)
    // Add inputs for oher properties of the model that you want to be submitted
    @Html.HiddenFor(m => m.ImageList[i].FileName)
}

which will generate the correct name attributes that relate to you model (i.e. name="ImageList[0].isSelected", name="ImageList[1].isSelected" etc)

Finally, you need to change the property to public IList<DBImages> ImageList { get; set; } (not IEnumerable<DBImages>). If the property cannot be changed, then you will need a custom EditorTemplate for typeof DBImages.

  • Side note: Just noticed that the property is `IEnumerable` - you will need to change it to `IList` or use a custom `EditorTemplate` for type of `DBImages` (refer [this answer](http://stackoverflow.com/questions/30094047/html-table-to-ado-net-datatable/30094943#30094943) for an example) –  May 31 '16 at 23:17
  • I've made these changes. What should be the parameter for the ActionResult? – gmalenko Jun 01 '16 at 14:45
  • Exactly what you have now - `[HttpPost] public ActionResult DeleteImages(Images model)` and then you can get the selected images using `var selected = model.ImageList.Where(x => x.isSelected);` but you don't generate any form controls for the other properties of `DBImages` so you will need to add `@Html.HiddenFor(m => m.ImageList[i].FileName)` etc for it to be meaningful. –  Jun 01 '16 at 22:02
  • This looks like this will work. Why does this work though? – gmalenko Jun 02 '16 at 17:42
  • @gmalenko, I have seen you edit with the sample output - but that is not what you code will generate - for example your view generates one submit button at the end, but the sample output is generating a submit button in each `
    ` (and your also generating invalid html because each submit button has the same `id` attribute) so its ot really clear what your actually doing. As you accepted this, I assume you have got it working now, but if not, let me know.
    –  Jun 02 '16 at 23:09
  • Thanks for the reply. I actually took out the second button (the one that generates with each image). It really dient work with the second button not being there either. i thought i took it out of the sample.output but i guess i didnt. Yes i got it to work.but the question was why or wvwn how your solution works. – gmalenko Jun 02 '16 at 23:16
  • Because the `HtmlHelper` method evaluate the expression and generate the `name` attribute based on the expression, so your code was generating `name="modellist[0].isSelected"` but you model does not contain a property named `modellist` which is a collection (the property is named `ImageList` so to bind to your model when you submit, it needs to be `name="ImageList[0].isSelected"`) –  Jun 02 '16 at 23:20
  • Excellent. Thank you! – gmalenko Jun 03 '16 at 15:02