繁体   English   中英

使用MVC使用CSV文件填充下拉列表

[英]Populating Dropdown with a CSV File using MVC

我是第一次使用MVC,在使用csv文件中的值填充下拉列表时遇到了一些麻烦。 csv文件有两列,第一列是位置名称,第二列是仅包含1和0的isOpen。

这是我在View中的首次尝试:

<div class="col-md-10">
    @{         
        List<SelectListItem> locations = new List<SelectListItem>();
        if (System.IO.File.Exists("~/Data/locations.csv"))
        {
            string[] lines = System.IO.File.ReadAllLines("~/Data/locations.csv");
            foreach (string line in lines)
            {
                string[] data = line.Split(',');
                if (data[1] == "1")
                {
                    locations.Add(new SelectListItem { Text = data[0], Value = data[0] });
                }
            }
        }
        Html.DropDownListFor(m => m.location, locations, new { htmlAttributes = new { @class = "form-control" } });
        Html.ValidationMessageFor(model => model.location, "", new { @class = "text-danger" });
    }
</div>

截至目前,这些代码均未运行,因为File.Exists函数自动默认为IIS Express文件夹并返回false。 我进行研究时找不到简单的答案,但是有一种方法可以正确地直接定向到我的项目文件夹吗? 还是在我的控制器中包含此代码是更好的做法?

public class Location
{
    //properties here that describe a location
}

public class CsvHelperLocationRepository : ILocationRepository
{
    private readonly string _dataFileLocation;

    public CsvHelperLocationRepository(string dataFileLocation)
    {
        _dataFileLocation = dataFileLocation;
    }

    public List<Location> GetLocations()
    {
        //use CsvHelper here to parse the CSV file and generate a list of Location objects to return
    }
}

public interface ILocationRepository
{
    List<Location> GetLocations();
}

public HomeController : Controller
{
    private readonly ILocationRepository _locationRepository;

    public HomeController()
    {
         //you really should use dependency injection instead of direct dependency like below
         _locationRepository = new CsvHelperLocationRepository(Server.MapPath("~/data/locations.csv");
    }

    public ActionResult SomeAction()
    {
        var model = new MyViewModel();
        model.Locations = _locationRepository.GetLocations();
        return View(model);
    }
}

您可以使用Server.MapPath从应用程序根目录相对URL( ~/ )转换为System.IO可以理解的绝对路径。

System.IO无法理解〜/语法。 您需要对文件路径进行预处理,然后再将其提交给System.IO。 这就是Server.MapPath的用处。此外,这种逻辑不属于视图。 相反,您应该拥有一个负责从数据源读取数据的类。 然后,您的控制器应利用该类检索所需的数据,然后将该数据添加到视图模型中,然后视图应显示该视图模型中的信息。 最后,不要自己手动解析CSV文件。 那是灾难的秘诀。 使用像CsvHelper这样的库来为您处理细微差别。

按照我所描述的那样执行代码将更加简洁(遵循“单一职责原则”),并且可以进行更多的单元测试并且更易于维护应用程序。

您应该使用类似Server.MapPath的方法来获取文件的物理路径。 如果您的Data目录位于应用程序的根目录中,则可以在文件位置使用~前缀,以便从应用程序的根目录获取路径。

var loc = Server.MapPath("~/Data/locations.csv");
if (System.IO.File.Exists(loc))
{
    string[] lines = System.IO.File.ReadAllLines(loc);
    foreach (string line in lines)
    {
        string[] data = line.Split(',');
        if (data[1] == "1")
        {
            locations.Add(new SelectListItem { Text = data[0], Value = data[0] });
        }
    }
}

虽然这可以解决问题,但我强烈建议您考虑一下泥瓦匠的意见。 您应该将CSV文件读取为另一个类( 单一职责原则 ),然后根据需要简单地使用该类。 如果使用接口包装它,则以后可以轻松地将您的实现与另一个健壮/经过测试的实现轻松切换,而无需更改大量代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM