locked
Issue with dropdownlistfor from Razor RRS feed

  • Question

  • User-1500491433 posted

    Hi,

    I am facing a strange problem with DropdownlistFor.

    Model

    public class LogFileModel
        {
            public List<SelectListItem> NamesList { get; set; }
    
            public string SelectedFileName { get; set; }
    
            [AllowHtml]
            public string SelectedFileContent { get; set; }
        }
     
    Controller:
     public class HomeController : Controller
        {
            private LogFileModel _logFileModel;
            string directoryPath = @"C:\Log";
    
            [HttpGet]
            public ViewResult Index()
            {
                _logFileModel = new LogFileModel();
                _logFileModel.NamesList = GetLogFileNames();
                return View(_logFileModel);
            }
    
            [HttpPost]
            [ValidateInput(false)]
            public ViewResult Index(LogFileModel logFileModel)
            {
                logFileModel.SelectedFileContent = System.IO.File.ReadAllText(Path.Combine(directoryPath, logFileModel.SelectedFileName));
               
                return View(logFileModel);
            }
    
            public ActionResult About()
            {
                return View();
            }
    
            private List<SelectListItem> GetLogFileNames()
            {
                var fileNamesQuery = from file in new DirectoryInfo(directoryPath).GetFiles()
                                     select new SelectListItem
                                            {
                                                Text = file.Name,
                                                Value = file.Name,
                                            };
                                        ;
                return fileNamesQuery.ToList<SelectListItem>();
            }
        }
    Index.cshtml
    @{
        ViewBag.Title = "Home Page";
    }
    @model LogViewer.Models.LogFileModel
    
    <p>
       @using (Html.BeginForm())
       {
           <p>Log files: 
               @Html.DropDownListFor(x => x.SelectedFileName, new[] {
                    new SelectListItem() {Text = "log1.txt", Value = "log1.txt"},
                    new SelectListItem() {Text = "log2.txt", Value = "log2.txt"},
                    new SelectListItem() {Text = "log3.txt", Value = "log3.txt"}
                    
                }, "Choose the Log file")
                <input type="submit" value="View" />
           </p>
           
       }
       @Html.TextAreaFor(m => m.SelectedFileContent, 15, 105, new { @style = "resize: none;" }) 
    </p>
    
    The above code works fine as I am adding the file names manually.
    But, if I use the below markup:
    @Html.DropDownListFor(x => x.SelectedFileName, @Model.NamesList, "Choose the Log file")
    and when I click on "View" button... I am getting following error:
    The ViewData item that has the key 'SelectedFileName' is of type 'System.String' but must be of type 'IEnumerable<SelectListItem>'.
    Can you please let me know how to fix this issue?
    Thursday, August 25, 2011 7:19 AM

Answers

  • User1642208711 posted

    I think I've identified the issue.

    Need to populate the NamesList property with some values in the post action method. Default model binder will not provide the model which has filled with custom list. Hence in the post action, the NamesList property will have null value. that would cause this issue.

    [HttpPost]
    [ValidateInput(false)]
    public ViewResult Index(LogFileModel logFileModel)
    {
        logFileModel.SelectedFileContent = System.IO.File.ReadAllText(Path.Combine(directoryPath, logFileModel.SelectedFileName));
        logFileModel.NamesList = GetLogFileNames(); //this line would resolve the issue.
        return View(logFileModel);
    }
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, August 25, 2011 8:43 AM
  • User1266497125 posted

    Rajesh,

    I've sent you the project back. The problem was that when the submit button was clicked, the POST version of your Index page would receive a null value for a list of log files. You need to collect them again in order to prevent this error from happening. It's resolved now.

    Regards,

    Huske

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, August 25, 2011 8:45 AM

All replies

  • User1266497125 posted

    @Html.DropDownListFor(x => x.SelectedFileName, @Model.NamesList, "Choose the Log file")

    Any particular reason why you are using @Model.NamesList inside an HtmlHelper extension?

    Regards,

    Huske

    Thursday, August 25, 2011 7:23 AM
  • User-1500491433 posted

    Huske,

    To be honest, I am not really sure. I am very new to this MVC and hence depending on examples on internet. Final goal is: We populate the dropdown list with list of files available in a folder. once the user selects the file name and clicks on "View" button, we need to show selected file content.

    Can you please help me in achieving this?

    Regards,

    Rajesh

    Thursday, August 25, 2011 7:32 AM
  • User1266497125 posted

    Hi Rajesh,

    First of all remove that @ from @Model.NamesList and try again. As for the rest, it seems that your code looks OK. This should be displaying the contents of the file inside a text area. Could you try again by fixing the issue I mentioned above?

    Regards,

    Huske

    PS. You might need to set permission on C:\Log to Everyone.

     

    Thursday, August 25, 2011 7:45 AM
  • User-1500491433 posted

    Hi Huske,

    Thank you for helping me. I tried with your suggestion. I am still getting the same result.

    I do not see any code attach facility here. Otherwise, I could have sent you my POC solution.

    Regards,

    Rajesh

    Thursday, August 25, 2011 7:56 AM
  • User1266497125 posted

    Sure, send me the solution and I'll check it out.

    Regards,

    Huske (distriktboj@msn.com)

    Thursday, August 25, 2011 8:03 AM
  • User-1500491433 posted

    Hi Huske,

    I sent the code to your MSN email account. Pleaes check it.

    Regards,

    Rajesh

    Thursday, August 25, 2011 8:15 AM
  • User1642208711 posted

    I think I've identified the issue.

    Need to populate the NamesList property with some values in the post action method. Default model binder will not provide the model which has filled with custom list. Hence in the post action, the NamesList property will have null value. that would cause this issue.

    [HttpPost]
    [ValidateInput(false)]
    public ViewResult Index(LogFileModel logFileModel)
    {
        logFileModel.SelectedFileContent = System.IO.File.ReadAllText(Path.Combine(directoryPath, logFileModel.SelectedFileName));
        logFileModel.NamesList = GetLogFileNames(); //this line would resolve the issue.
        return View(logFileModel);
    }
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, August 25, 2011 8:43 AM
  • User1266497125 posted

    Rajesh,

    I've sent you the project back. The problem was that when the submit button was clicked, the POST version of your Index page would receive a null value for a list of log files. You need to collect them again in order to prevent this error from happening. It's resolved now.

    Regards,

    Huske

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, August 25, 2011 8:45 AM
  • User-1500491433 posted

    Hi Raja,

    You are right. It is working fine now. I have one question. Why do we need to pass such data always? Is it not a repititive data transfer? Just want to understand.

     

    Regards,

    Rajesh

    Thursday, August 25, 2011 8:49 AM
  • User-1500491433 posted

    Thanks Huske,

    Yes, you are right. Raja was giving the same solution :).

    Regards,

    Rajesh

    Thursday, August 25, 2011 8:51 AM
  • User1266497125 posted

    Hi Rajesh,

    Raja explained why that might be a problem and it has to do with the default model binder. Here is an article by Phil Haack about default model binder and collections. This should give you a better idea http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

    Regards,

    Huske

     

    Thursday, August 25, 2011 8:53 AM
  • User1642208711 posted

    Why do we need to pass such data always? Is it not a repititive data transfer?

    Basically ASP.Net is stateless.

    To overcome this, we have ViewState and ControlState in ASP.Net. The data and the control information will be stored in a hidden html field as encrypted format and in the post back, control and data will be restored from the viewstate.

    But unfortunately, ASP.Net MVC doesn't have the ViewState feature. Hence we need to re-populate the data for the controls manually in the post action too.

    That's the reason, default model binder was unable to populate those custom values.

    Thursday, August 25, 2011 8:57 AM
  • User-1500491433 posted

    Huske/ Raja,

    Thank you very much for your explanations Smile

    Regards,

    Rajesh

    Thursday, August 25, 2011 9:07 AM