-1

I am trying to grab files from a directory and I am trying to let the user select a file from a list to be later processed.

This is the code that gets the files.

    [HttpGet]
    public ActionResult GetFiles()
    {
        DirectoryInfo dinfo = new DirectoryInfo(@"C:\TestDirectory");
        List<FileInfo> Files = dinfo.GetFiles("*.txt").ToList();

        return PartialView("_File", Files);
    }

And this is the partial view that that is going to be in the modal for now.

@model List<FileInfo>

@Html.ListBoxFor(model => model, new SelectList(Model).AsEnumerable())

How I am calling the partial view from main view:

<div class="row">
<div class="modal fade" id="bootstrapDialog" tabindex="-1" role="dialog" aria-labelledby="myModal-label" aria-hidden="true"></div>
</div>

<div class="btn btn-default browseButton">
<span class="glyphicon glyphicon-folder-open browseDialog" data-url="@Url.Action("GetFiles","Home", null)"></span> 
<span class="browseDialog" data-url="@Url.Action("GetFiles","Home", null)">Browse...</span>
</div>

@section scripts {
<script>
       $(document).ready(function () {

        $('.browseDialog').click(function () {

            var url = $(this).data('url');

            $.get(url, function (data) {

                $('#bootstrapDialog').html(data);

                $('#bootstrapDialog').modal('show');

            });

        });
   });

</script>
}

The file information is being retreived but the listbox is not created. The listbox gives an except that the value cannot be null or empty. Do I have to create something else that has to be passed into this listbox?

And how would I allow the user to select an item to pass back to the screen behind to modal to populate a textbox?

user3266638
  • 429
  • 8
  • 25
  • How are you calling the partial from the main view? (and you need a separate `IEnumerable` property to bind the selected values to, and `Files` should be `IEnumerable`, not `List`) –  Oct 22 '18 at 21:01
  • @StephenMuecke I added the code that calls this partial from the main. Hoping it makes sense but basically upon pressing a button I make a call to the function and return the partial view to a modal. I think I included everything it uses. So instead of a list of file info it has to be a selectlistitem? Would it be better to pass in a viewmodel to the partial view? I don't think I need anything but the list of files. – user3266638 Oct 22 '18 at 21:15
  • This tutorial might help, you can use DropDownListFor: https://odetocode.com/blogs/scott/archive/2013/03/11/dropdownlistfor-with-asp-net-mvc.aspx – Hooman Bahreini Oct 22 '18 at 21:22
  • Yes you should be using a view model (refer the code in [this question](https://stackoverflow.com/questions/34366305/the-viewdata-item-that-has-the-key-xxx-is-of-type-system-int32-but-must-be-o) for an example (and using `new SelectList(Model).AsEnumerable()` would not work since your model is `List` and you are not specifying the properties you want to use for the `Value` and `Text` properties) –  Oct 22 '18 at 21:22

1 Answers1

1

Both @model List<FileInfo> and new SelectList(Model).AsEnumerable() usage seem to be wrong, since you're not specifying both text and value to be populated in the list. You should create a viewmodel with setup like this:

public class ViewModel
{
    // other properties

    public string SelectedFile { get; set; }

    // options list
    public IEnumerable<SelectListItem> FilesList { get; set; }
}

Then, in your controller action, create List<SelectListItem> instance from List<FileInfo> by using Select() extension method and picking Name property as both option text and value:

[HttpGet]
public ActionResult GetFiles()
{
    DirectoryInfo dinfo = new DirectoryInfo(@"C:\TestDirectory");
    List<FileInfo> Files = dinfo.GetFiles("*.txt").ToList();

    var model = new ViewModel();

    // use file name to generate option list
    model.FilesList = Files.Select(x => new SelectListItem { Text = x.Name, Value = x.Name }).ToList();

    return PartialView("_File", model);
}

Finally, create a DropDownListFor helper with list populated from FilesList property:

@model ViewModel

@Html.DropDownListFor(model => model.SelectedFile, Model.FilesList, ...)

Afterwards, you can retrieve the selected file by using string property mentioned above, such like Server.MapPath().

Additional note:

If you want to select multiple file names rather than single file name, then use IEnumerable<string> property together with ListBoxFor helper:

ViewModel

public IEnumerable<string> SelectedFiles { get; set; }

View

@Html.ListBoxFor(model => model.SelectedFiles, Model.FilesList, ...)
Tetsuya Yamamoto
  • 24,297
  • 8
  • 39
  • 61