2011-07-15 13 views
1

私はLinqToSqlでASP.NET MVCプロジェクトに取り組んできました。アプリケーションには、UI、ビジネス、データの3つのレイヤーがあります。ASP.NET MVC - 多層疑問

最後の数日、私は(まだ私は)Excelファイルのアップロードを実装していました。そこで、私のコントローラはアップロードされたファイルを受け取り、何かをして、ビジネスに、次にデータに情報を渡します。しかし、その発展とともにいくつかの疑念が浮上しました。

  1. Excelファイルを検証する必要があります。ここでは

    は、私の疑問のいくつか(私は弾丸を表示する最も簡単な方法だと思います)です。アプリケーションは、ワークシート値が正しいかどうかを検証しなければならない場合、データベースに挿入/更新する必要があります。私はコントローラーまたはビジネスでExcelを検証する必要がありますか?

  2. このExcelでは、DBにデータを挿入することがあります。例えば、new Product(); UIレイヤーに新しいインスタンスを作成する際に問題がありますか、それともビジネスで行うのが良いですか? UIからビジネスにオブジェクトを渡す方が良いのでしょうか、すべてのクラスのプロパティを渡してビジネスにオブジェクトを作成する方が良いでしょうか?

  3. このExcelのアクションでは、ワークシートが終了したかどうかを確認し、セルに値があるかどうかを確認し、アップロードされたファイルなどのDataTableを生成するなどのヘルパーメソッドがあります。これらのヘルパーメソッドはどこに配置する必要がありますか?現時点では、それらはUIレイヤーにあります(コントローラと同じ)。

  4. Excelのことを忘れて、単純なProductフォームのページを想像してみてください。 POSTでは、ControllerはFormCollectionを受け取ります。このFormCollectionをController上で扱うべきか、それともビジネスとビジネスに渡すべきかすべてのことを行うべきでしょうか?

ご迷惑をおかけして申し訳ありません。私はまた、私のコードをリファクタリングしようとしていると、 "脂肪コントローラ"の問題は私のドアの右です!

ありがとうございます!

答えて

2

脂肪コントローラを実際に避けるべきです。しかしいつものようには簡単に言った

あなたの質問に例を挙げてお答えします。いつものようにあなたが(任意の弱FormCollectionViewDataを入力使用しない)ユーザーは、このアクションに送信するデータを表現するビューモデルを設計することにより

public class UploadViewModel 
{ 
    [Required] 
    public HttpPostedFileBase File { get; set; } 
} 

を開始すると、我々は、コントローラに移動:

public ProductsController: Controller 
{ 
    private readonly IProductsService _service; 
    public ProductsController(IProductsService service) 
    { 
     _service = service; 
    } 

    public ActionResult Upload() 
    { 
     var model = new UploadViewModel(); 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Upload(UploadViewModel model) 
    { 
     if (!ModelState.IsValid) 
     { 
      // The model was not valid => redisplay the form 
      // so that the user can fix his errors 
      return View(model); 
     } 

     // at this stage we know that the model passed UI validation 
     // so let's hand it to the service layer by constructing a 
     // business model 
     string error; 
     if (!_service.TryProcessFile(model.File.InputStream, out error)) 
     { 
      // there was an error while processing the file => 
      // redisplay the view and inform the user 
      ModelState.AddModelError("file", error); 
      return View(model); 
     } 

     return Content("thanks for submitting", "text/plain"); 
    } 
} 

最後のビットはサービスレイヤです。 2つの依存関係があります:最初のものは入力ストリームの解析とProductのリストの返信を処理し、2番目の処理はそれらの製品をデータベースに永続化させます。ただ、このような

public class ExcelProductsParser: IProductsParser 
{ 
    public IEnumerable<Product> Parse(Stream input) 
    { 
     // parse the Excel file and return a list of products 
     // that you might have extracted from it 
     ... 
    } 
} 

とリポジトリ:

public class Linq2SqlProductsRepository: IProductsRepository 
{ 
    public void Save(IEnumerable<Product> products) 
    { 
     // save the products to the database 
     ... 
    } 
} 

備考:あなたは豊かにでき

その後
public class ProductsService: IProductsService 
{ 
    private readonly IProductsParser _productsParser; 
    private readonly IProductsRepository _productsRepository; 
    public ProductsService(IProductsParser productsParser, IProductsRepository productsRepository) 
    { 
     _productsParser = productsParser; 
     _productsRepository = productsRepository; 
    } 

    public bool TryProcessFile(Stream input, out string error) 
    { 
     error = ""; 
     try 
     { 
      // Parse the Excel file to extract products 
      IEnumerable<Product> products = _productsParser.Parse(input); 

      // TODO: Here you may validate whether the products that were 
      // extracted from the Excel file correspond to your business 
      // requirements and return false if not 

      // At this stage we have validated the products => let's persist them 
      _productsRepository.Save(products); 
      return true; 
     } 
     catch (Exception ex) 
     { 
      error = ex.Message; 
     } 
     return false; 
    } 
} 

はもちろん、あなたがそれらの依存関係の2つの実装を持っているでしょう関連付ける可能性のあるメタデータを表す追加のプロパティを持つビューモデルoこのファイルをアップロードし、フォームに対応する入力フィールドがある可能性があります。次に、単純なStreamの代わりにTryProcessFileメソッドに渡すビジネスモデルを定義することができます。この場合、をコントローラーアクションで使用して、UploadViewModelと定義するこの新しいビジネスモデルをマップすることができます。

+0

ダーリン、ご意見ありがとうございます!それは私のコードをリファクタリングするためのいくつかの固い思考を作成するために私を助けた! – AndreMiranda

関連する問題