Там действительно 2 части в вашем вопросе. Часть анализа XML (которая не имеет ничего общего с ASP.NET MVC) и частью ASP.NET MVC. Так как ваш вопрос помечен asp.net-mvc
, давайте сначала ответим на эту часть. Таким образом, вы указываете модель представления. Что-то вроде этого:
public class BrandsViewModel
{
public string Brand { get; set; }
public IEnumerable<SelectListItem> Brands { get; set; }
}
затем действие контроллера:
public ActionResult Index()
{
BrandsViewModel model = ...
return View(model);
}
и, наконец, вид части:
@model BrandsViewModel
@using (Html.BeginForm())
{
@Html.DropDownListFor(x => x.Brand, Model.Brands)
<button type="submit">OK</button>
}
Хорошо, это где ASP.NET MVC часть заканчивается в вашем вопрос. Теперь идет парсинг XML. Существует несколько способов анализа XML на C#. Например, вы можете использовать класс XDocument.
Конечно, перед анализом XML вы должны иметь XML. То, что вы показали в своем вопросе, - это не XML. Это строка. Вы должны сначала исправить это и иметь действительный XML. Пример:
<Brands>
<Brand>
<BrandId>1</BrandId>
<BrandNo>20</BrandNo>
<BrandName>ABC</BrandName>
</Brand>
<Brand>
<BrandId>2</BrandId>
<BrandNo>30</BrandNo>
<BrandName>XYZ</BrandName>
</Brand>
</Brands>
Теперь, когда у вас есть действительный XML, переходим к использованию и используем синтаксический анализатор XML.
var brands =
from brand in XDocument.Load("brands.xml").Descendants("Brand")
select new SelectListItem
{
Value = brand.Element("BrandId").Value,
Text = brand.Element("BrandName").Value
};
и теперь давайте сделаем 2 работать вместе:
public ActionResult Index()
{
var brandsFile = Server.MapPath("~/app_data/brands.xml");
var brands =
from brand in XDocument.Load(brandsFile).Descendants("Brand")
select new SelectListItem
{
Value = brand.Element("BrandId").Value,
Text = brand.Element("BrandName").Value
};
var model = new BrandsViewModel
{
Brands = brands
};
return View(model);
}
Здесь мы можем видеть, что мы сильно связаны из логики действий контроллера с XML разбора логики, которая плохо. Вы можете ввести абстракцию (интерфейс), которая будет введена в конструктор контроллера, а затем использована действием. Затем вы можете предоставить конкретную реализацию этой абстракции, которая будет выполнять фактический синтаксический анализ XML и настроить инфраструктуру инъекции зависимостей, чтобы передать ее контроллеру.
Так что давайте сделаем это. Давайте определим модель домена, которая будет представлять наши бренды:
public class Brand
{
public string Id { get; set; }
public string Name { get; set; }
}
Прохладный. Теперь, что мы хотим делать с этими брендами? Извлеките их список. Давайте определим наш контракт:
public interface IBrandsRepository
{
Brand[] Get();
}
ОК, мы указали, какие операции нам нужны с нашими брендами. Теперь у нас может быть наш контроллер таким образом:
public class BrandsController: Controller
{
private readonly IBrandsRepository _repository;
public BrandsController(IBrandsRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
var brands = _repository.Get().Select(b => new SelectListItem
{
Value = b.Id,
Text = b.Name
});
var model = new BrandsViewModel
{
Brands = brands
};
return View(model);
}
}
По-прежнему существует возможность для улучшения этого действия контроллера. Обратите внимание, что мы запрашиваем репозиторий и получаем список доменных моделей (Brand
) и преобразуем эту модель домена в модель представления.Это громоздко и загрязняет нашу логику контроллера. Было бы лучше экстернализировать это сопоставление в отдельный слой. Лично я использую для этого AutoMapper. Это основа lightwight, которая позволяет определить отображения между различными классами в беглом пути, а затем просто передать его экземпляры типа источника и плюнет вам экземпляры типа мишени:
public class BrandsController: Controller
{
private readonly IBrandsRepository _repository;
public BrandsController(IBrandsRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
var brands = _repository.Get();
var model = new BrandsViewModel
{
Brands = Mapper.Map<IEnumerable<Brand>, IEnumerable<SelectListItem>>(brands)
};
return View(model);
}
}
Так мы делаем прогресс здесь. Теперь мы могли бы реализацию нашего контракта:
public class BrandsRepositoryXml: IBrandsRepository
{
private readonly string _brandsFile;
public BrandsRepositoryXml(string brandsFile)
{
_brandsFile = brandsFile;
}
public Brand[] Get()
{
return
(from brand in XDocument.Load(_brandsFile).Descendants("Brand")
select new Brand
{
Id = brand.Element("BrandId").Value,
Name = brand.Element("BrandName").Value
})
.ToArray();
}
}
И последний шаг головоломки настроить некоторые DI рамок, чтобы придать надлежащую реализацию нашего договора в контроллер. Есть как gazzilion каркасов DI для .NET. Просто выберите один. Это не имеет большого значения. Попробуйте Ninject.MVC3 NuGet. Это классно и легко настроить. Или, если вы не хотите использовать сторонние рамки DI, просто напишите обычай dependency resolver.
Я не понимаю, что часть «не XML, это строка». Может быть, я плотный, но как ваш XML отличается от OP? –
@CharlieKilian, смотрите внимательнее. Вы видите это ' XYZ'? Также вы видите закрывающий тег '' в XML OP? Я не. –
Ах. Нет, я этого не делал, но сейчас. Хороший улов с вашей стороны. Мои извинения. –