脂肪コントローラを実際に避けるべきです。しかしいつものようには簡単に言った。
あなたの質問に例を挙げてお答えします。いつものようにあなたが(任意の弱FormCollection
かViewData
を入力使用しない)ユーザーは、このアクションに送信するデータを表現するビューモデルを設計することにより
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
と定義するこの新しいビジネスモデルをマップすることができます。
ダーリン、ご意見ありがとうございます!それは私のコードをリファクタリングするためのいくつかの固い思考を作成するために私を助けた! – AndreMiranda