我是第一次使用MVC,而且我在使用csv文件中的值填充下拉列表时遇到了一些麻烦。 csv文件是两列,第一列是位置名称,第二列是isOpen,只包含1和0。
这是我在观点中的第一次尝试:
<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。我在研究时找不到简单的答案,但有没有办法正确指向我的项目文件夹呢?或者在我的控制器中使用此代码会更好吗?
答案 0 :(得分:2)
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不理解〜/ syntax。在将文件路径交给System.IO之前,您需要预先处理文件路径。这就是Server.MapPath所在的位置。此外,这种逻辑不属于视图。相反,您应该有一个负责从数据源读取数据的类。然后,您的控制器应该利用该类检索所需的数据,将该数据添加到视图模型,然后视图应该从视图模型中显示该信息。最后,不要自己手动解析CSV文件。那是灾难的秘诀。使用可以处理细微差别的库,例如CsvHelper。
实现我所描述的代码将更加清晰(遵循单一责任原则),从而使单元可测试更容易,更易于维护。
答案 1 :(得分:1)
您应该使用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文件的抽象读取到另一个类(Single responsibility principle),并根据需要简单地使用该类。如果使用接口包装它,您可以轻松地在以后轻松地使用另一个强大/经过测试的实现切换实现,而无需更改大量代码。