1

私のMVCアプリケーションには、次のXMLを返すサービス呼び出し(http://dev-service.test.com/api/brands?active=true)があります。

<Brands>
  <Brand>
  <BrandId>1</BrandId>
  <BrandNo>20</BrandNo>
  <BrandName>ABC</Domain>
  </Brand>

  <Brand>
  <BrandId>2</BrandId>
  <BrandNo>30</BrandNo>
  <BrandName>XYZ</Domain>
  </Brand>
<Brands>

ユーザーコントロールの1つで、ドロップダウンリストにBrandName値を入力したいと思います。たくさんのプロパティを含むViewModelがすでにあります。ドロップダウンにこのXMLの値を入力するにはどうすればよいですか?

PS:私はMVCに不慣れで、ビューモデルなどの基本をまだ学んでいます。

4

2 に答える 2

10

あなたの質問には本当に2つの部分があります。XML解析部分(厳密にはASP.NET MVCとは関係ありません)とASP.NETMVC部分。あなたの質問はでタグ付けされているので、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.NETMVCの部分が質問の最後になります。次に、XML解析の部分があります。C#でXMLを解析する方法はいくつかあります。たとえば、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();
}

OK、ブランドで必要な操作を指定しました。これで、コントローラーを次のように表示できます。

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を使用しています。これは軽量のフレームワークであり、異なるクラス間のマッピングを流暢に定義し、ソースタイプのインスタンスを渡すだけで、ターゲットタイプのインスタンスを吐き出すことができます。

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フレームワークを構成することです。.NET用のDIフレームワークの群れのようなものがあります。1つ選んでください。それは本当に重要ではありません。Ninject.MVC3NuGetを試してください。ちょっとクールでセットアップも簡単です。または、サードパーティのDIフレームワークを使用したくない場合は、カスタムの依存関係リゾルバーを作成するだけです。

于 2012-04-11T19:29:03.267 に答える
0

Xmlを解析するには、次の簡単で汚い例を使用できます。

 string 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> ";

        System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
        doc.LoadXml(xml);

        var brands = (
            from node in doc.SelectNodes("//Brands/Brand").Cast<System.Xml.XmlNode>()
            select new
            {
                BrandId = node.SelectSingleNode("BrandId").InnerText,
                BrandNo = node.SelectSingleNode("BrandNo").InnerText,
                BrandName = node.SelectSingleNode("BrandName").InnerText

            }).ToList();

私の場合、Brandという強い型のクラスを作成し、解析対象に一致するプロパティを指定して、ノードを解析します。

于 2012-04-11T19:40:59.227 に答える