簡體   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