プロトタイプMISの構築例について、Visual Studio 2015のASP.NET MVCを知っている

今年、学期論文として、てんかんの治療のための小規模な私立クリニック用の簡単な医療情報システム(MIS)を作成する必要がありました。



診療所の患者のデータベースはすでに存在し、1998年に当時のMicrosoft Accessに書き戻されました(そして、美しいユーザーインターフェイスでも)、それは1か所でしか機能しませんでした-マネージャーのコンピューター上で、完全にサポートになりました不可能。 そのため、何か新しいものを導入する必要性は長い間熟しています!



すぐに言ってやった。 すぐに(結局、コース時間を過ごすために)仕事をする必要がありましたが、同時に私は自分の仕事をできるだけ面白くしたかったのです。 長い間、ASP.NET MVCを理解したかったため、C#とMVCの一般原則に少し精通していたため、最新のVisual Studio 2015 RCをダウンロードして作業を開始しました。



カットの下で-技術を探求し、すべての落とし穴に遭遇するようなシステムを開発するプロセス全体。 この記事は、プログラミングに精通しており、かつてMVCフレームワークのチュートリアルブログを作成し、より興味深いことを行う方法を学びたいすべての人に役立ちます。



それでは始めましょう!



問題の声明



てんかんの治療のための小さな診療所の患者の単一のデータベースを作成する必要があります。 センターの経営陣と話し合った後、次の要件が形成されました。



実装



ASP.NET MVCの仕組みを理解するための出発点は、 http: //www.asp.net/mvcの公式チュートリアルです。 初めての仕事では、これで十分です。 Habré教科書も見てみましたが、個人的にはあまりにも専門的でした。



MicrosoftのWebサイトのマニュアルから(気分を良くするために手でやるほうがよい)、プロセスの一般的な仕組み、コントローラーの作業、1つのモデルの表現は優れていますが、より複雑なアプリケーションを作成する方法は明確ではありません。 それが私がやろうとしていることです。



基本を扱ったので、仕事に取り掛かります。



新しいASP.NETアプリケーションを作成し、Ctrl-F5を使用して起動します。



プロジェクト作成
画像



モデルを書く



作業の最初の段階は、使用されるモデルの説明です。 私の場合、すべてがシンプルでした。 古いAccessデータを迅速に統合する必要があるため、最も簡単なソリューション-古いデータスキームを正確にコピーし、必要な場合にのみ変更する必要がありました。







つまり、レセプション(日付と医師)に関連付けられた患者(個人データ)です。 医師は予約ごとに、病歴、診断、予約など、さまざまな種類の文書を追加できます。 そして、そのような既往歴、診断、および他のドキュメントにはそれぞれ、辞書からのタイプがあります-列挙を持つ別個のテーブル。



さて、Modelsフォルダーに新しいPacient.csファイルを作成し、各モデルを1つずつ説明します。 例:



複数のモデルを追加する
public class DiagnosisType { public int ID { get; set; } [DisplayName("")] public String name { get; set; } [DisplayName("")] [DataType(DataType.MultilineText)] public String description { get; set; } } public class Diagnosis { public int ID { get; set; } [DisplayName("")] public DiagnosisType type { get; set; } [DisplayName("")] [DataType(DataType.MultilineText)] public String comments { get; set; } } public class VisitDate { public int ID { get; set; } public int doctorID { get; set; } [DisplayName(" ")] public DateTime date { get; set; } public List<Anamnesis> anamnesis { get; set; } public List<Debut> debutes { get; set; } public List<Diagnosis> diagnoses { get; set; } public List<Research> researches { get; set; } public List<Assigment> assigments { get; set; } public List<Neurostatus> neurostatuses { get; set; } public List<Review> reviews { get; set; } public List<Syndrome> syndromes { get; set; } } public enum Sex { [Display(Name = "")] A, [Display(Name = "")] F, [Display(Name = "")] M, [Display(Name = " ")] N, [Display(Name = "")] O, [Display(Name = "")] U } public class Pacient { public int ID { get; set; } [DisplayName(" ")] public Doctor doctor { get; set; } [DisplayName("")] public String name { get; set; } [DisplayName(" ")] public String cart { get; set; } [DisplayName("")] [DataType(DataType.PhoneNumber)] [Phone] public String phone { get; set; } [DisplayName("   ")] [DataType(DataType.Date)] public DateTime dateOfregistration { get; set; } [DisplayName("")] public Sex sex { get; set; } [DisplayName(" ")] [DataType(DataType.Date)] [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime birthday { get; set; } [DisplayName("")] public String mother { get; set; } [DisplayName("")] public String father { get; set; } [DisplayName(" ")] public String adress { get; set; } [DisplayName("")] [DataType(DataType.Html)] [AllowHtml] public String comments { get; set; } public List<VisitDate> visits { get; set; } }
      
      







モデルの残りのクラスは、類推によって決定されます。



備考:





Entity Frameworkのモデルからデータベーステーブルを生成するための一般的なアイデア:



素晴らしい、すべてのモデルを設計しました。 次に、これらがデータベースのモデルであることをEntity Frameworkに伝える必要があります。 これを行うには、新しい接続コンテキストを作成します。 1つのコンテキスト-1つのデータベース



コンテキスト作成コード
 public class PacientDBContext : DbContext { public DbSet<Pacient> pacients { get; set; } public DbSet<AnamnesisEventType> anamnesisTypes { get; set; } public DbSet<Anamnesis> anamneses { get; set; } public DbSet<Debut> debutes { get; set; } public DbSet<DebutType> debuteTypes { get; set; } public DbSet<Diagnosis> diagnoses { get; set; } public DbSet<DiagnosisType> diagnosisTypes { get; set; } public DbSet<Research> researches { get; set; } public DbSet<ResearchType> researchTypes { get; set; } public DbSet<Medicine> medicines { get; set; } public DbSet<MedicineType> medicineTypes { get; set; } public DbSet<Neurostatus> neurostatuses { get; set; } public DbSet<NeuroStatusType> neuroStatusTypes { get; set; } public DbSet<Assigment> assigments { get; set; } public DbSet<AssigmentType> assigmentTypes { get; set; } public DbSet<Syndrome> syndromes { get; set; } public DbSet<SyndromeType> syndromeTypes { get; set; } public DbSet<Review> reviews { get; set; } public DbSet<VisitDate> visits { get; set; } public DbSet<Doctor> doctors { get; set; } } </lang> </spoiler> , , ,    .    -      Web.config   : <spoiler title="  Web.config"> <source lang="xml"> <connectionStrings> <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\Users.mdf;Initial Catalog=aspnet-WebApplication2-20150526031246;Integrated Security=True" providerName="System.Data.SqlClient" /> <add name="PacientDBContext" connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Pacients.mdf;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings>
      
      







注意! 詐欺! デフォルトでは、デフォルトコンテキストはData Source =(LocalDb)\ MSLocalDBであり、展開前にSQL Server Express 2014であることが判明しましたが、ホスティングはそれについて何も知りませんでした! Express 2012をすぐにインストールし(そうでない場合)、 v11.0で修正することをお勧めします。



これで、アプリケーションを起動するだけでシステムは新しいデータベースを作成します... これは、このデータへのアクセスを最初に要求したときに初めて起こりました。 ただし、サーバーブラウザーの左側のデータにアクセスすると、作成されたデータベースを確認できます。







ちなみに、後でモデルを少し変更したり、何かを追加したりする必要がある場合は、ベースを再作成する必要はありません。 これには自動移行があります。 操作手順:パッケージマネージャーコンソールを開き、 Enable-Migrations –EnableAutomaticMigrations -ContextTypeName WebApplication2.Models.PacientDBContexコマンドを使用して移行を有効にし、データベースを更新するために、今後update-databaseコマンドを発行します。 詳細はこちら







コントローラーの追加



次のステップは、システム内の各データタイプにコントローラーを追加することです。 プロセスは自動的に手動で行われます。 データ型ごとにコントローラーを追加する必要があります。



コントローラーを追加するプロセス








これで、すべてのデータを表示、追加、変更するためのコントローラーと標準ビューができました! Django管理パネルのように、おそらくバインドできますか?



そしていや! 標準では、モデルレベルではそのような関係がありますが、患者を入院日と関連付けることはできません。 この瞬間から、楽しみが始まります! 患者ページにすべてのデータを表示する必要があります。



これを行うには、PacientsContrtoller.csのDetailsメソッドを変更します。



 public ActionResult Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } //db. Pacient pacient = db.pacients .Include(p=>p.doctor) .Include(p => p.visits.Select(w => w.anamnesis.Select(r=>r.type))) .Include(p => p.visits.Select(w => w.debutes.Select(r => r.type))) .Include(p => p.visits.Select(w => w.diagnoses.Select(r => r.type))) .Include(p => p.visits.Select(w => w.researches.Select(r => r.type))) .Include(p => p.visits.Select(w => w.anamnesis.Select(r => r.type))) .Include(p => p.visits.Select(w => w.neurostatuses.Select(r => r.type))) .Include(p => p.visits.Select(w => w.assigments.Select(r => r.type))) .Include(p => p.visits.Select(w => w.syndromes.Select(r => r.type))) .Include(p => p.visits.Select(w => w.reviews)) .Where(p=>p.ID == id).Single(); pacient.visits.Sort(delegate (VisitDate t1, VisitDate t2) { return t2.date.CompareTo(t1.date); }); return View(pacient); }
      
      





このひどくいLINQクエリでは、絶対にすべての患者データを読み込むようシステムに要求します。 これには、Includeが使用され、ネストの第2レベルにはSelectが使用されます。



CVで名前または単語による検索を実装するには、トリッキーなリクエストも使用します。



 public ActionResult SearchByName(String name = "", String mode = "name") { if (mode.Equals("name")) return PartialView(db.pacients.Where(p => p.name.Contains(name)).ToList()); else { var results = db.pacients.Where(p => p.visits.Any(vd => vd.reviews.Any(r => r.comments.ToLower().Contains(name.ToLower())))); return PartialView(results.ToList()); } }
      
      





コントローラーメソッドのパラメーターは、GETリクエスト(疑問符の後のアドレスバー)に含まれているものであることを思い出します。



残りのメソッドは基本的に変更されません。



各ドキュメントコントローラー(医療履歴、診断、履歴書など)で、標準のメソッドに代わる4つの新しいメソッドを作成しました。これらはAJAXの部分ビューを返します。



実装
 public ActionResult pacientDetails(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Anamnesis anamnesis = db.anamneses.Include(p => p.type).Where(p => p.ID == id).First(); if (anamnesis == null) { return HttpNotFound(); } return PartialView("~/views/Anamnesis/pacientDetails.cshtml", anamnesis); } // GET: Anamnesis/Create public ActionResult pacientCreate(int visitID, int num) { newAnamnesis na = new newAnamnesis(); na.visitID = visitID; na.num = num; na.anamnesis = new Anamnesis(); na.eventTypes = db.anamnesisTypes.ToList(); return PartialView(na); } public ActionResult Create(newAnamnesis data) { VisitDate visit = db.visits.Include(v => v.anamnesis).Where(v => v.ID == data.visitID).First(); if (visit == null) return RedirectToAction("Index", "Pacients"); Pacient pacient = db.pacients.Where(p => p.visits.Any(v => v.ID == data.visitID)).First(); if (pacient == null) return RedirectToAction("Index", "Pacients"); if (ModelState.IsValid) { AnamnesisEventType type = db.anamnesisTypes.Where(a => a.ID == data.anamnesis.type.ID).First(); data.anamnesis.type = type; visit.anamnesis.Add(data.anamnesis); db.SaveChanges(); return PartialView("/views/Anamnesis/pacientDetails.cshtml", data.anamnesis); } return PartialView("/views/Anamnesis/pacientCreate.cshtml", data); } // GET: Anamnesis/Edit/5 public ActionResult pacientEdit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Anamnesis anamnesis = db.anamneses.Include(p=>p.type).Where(p=>p.ID == id).First(); if (anamnesis == null) { return HttpNotFound(); } return PartialView(anamnesis); } // POST: Anamnesis/Edit/5 [HttpPost] [ValidateAntiForgeryToken] public ActionResult pacientEdit([Bind(Include = "ID,comments")] Anamnesis anamnesis) { if (ModelState.IsValid) { db.Entry(anamnesis).State = EntityState.Modified; db.SaveChanges(); return pacientDetails(anamnesis.ID); } return PartialView(anamnesis); } // GET: Anamnesis/Delete/5 public ActionResult pacientDelete(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Anamnesis anamnesis = db.anamneses.Find(id); if (anamnesis == null) { return HttpNotFound(); } db.anamneses.Remove(anamnesis); db.SaveChanges(); return PartialView(); }
      
      







デフォルトのビューを変更する



ここでのタスクは、患者に関する表現を変更して、患者に関するすべての情報を表示し、ページを更新せずに患者が編集できるようにすることです。



メインページでは、選択する2つのパラメーターで検索フォームを表示し、JQueryを使用して結果を動的にロードします。



患者リストページコード-Views / Pacient / Details.cshtml
 @{ ViewBag.Title = "Index"; } <div class="row"> <div class="col-md-6"> <h2> </h2> </div> <div class="col-md-6"> <a href="/Pacients/Create/" class="btn btn-success pull-right" style="margin-top: 20px; margin-right: 20px;"><span class="glyphicon glyphicon-plus"></span></a> </div> </div> <div> <form class="form-horizontal"> <div class="input-group input-group-lg col-md-12 bs-callout bs-callout-primary"> <label for="search" class="sr-only">  </label> <div class="col-sm-10"> <input type="text" placeholder="  " name="name" class="col-sm-10 form-control" id="search" /> </div> <div class="col-sm-2"> <input type='button' id="submit" value='' class="btn" /> </div> <div class="col-sm-10"> <label class="radio-inline"> <input type="radio" name="searchOptions" id="searchByName" value="name" checked>   </label> <label class="radio-inline"> <input type="radio" name="searchOptions" id="reviewSearch" value="review">   </label> </div> </div> </form> </div> <div id="results"></div> <script type="text/javascript"> $(document).ready(function () { //$('#submit').cha $('#submit').click(function (e) { e.preventDefault(); var name = $('#search').val(); var mode = "name"; if ($("#reviewSearch").prop("checked")) { mode = "review" } name = name.replace(new RegExp(" ", 'g'), "%20"); $('#results').load("/Pacients/SearchByName?name=" + name + "&mode="+mode); }); $('#search').keypress(function (event) { if ($("#reviewSearch").prop("checked")) return; if (event.which == 13) { event.preventDefault(); } var name = $('#search').val(); var mode = "name"; if ($("#reviewSearch").prop("checked")) { mode = "review" } name = name.replace(new RegExp(" ", 'g'), "%20"); $('#results').load("/Pacients/SearchByName?name=" + name + "&mode=" + mode); }); }); </script>
      
      







新しい患者と変更を作成するためのテンプレートは変更されません。 しかし、患者に関する詳細情報のページは、一度に複数の提出に分割する必要がありました。



患者ページのヘッダー
 @model WebApplication2.Models.Pacient @{ ViewBag.Title = "Details"; } <div class="row"> <div class="col-md-2" style=" margin-top: 30px;"> <a href="@Url.Action("Index" )" class = "btn btn-default btn-lg"><span class="glyphicon glyphicon-backward" aria-hidden="true"></span>  </a> </div> <div class="col-md-6"><h2>@Html.DisplayFor(model => model.name)</h2> <h4>@Html.DisplayNameFor(model => model.doctor): @Html.DisplayFor(model => model.doctor.name)</h4> </div> @if (Model.visits.Count==0 || !(Model.visits.First().date.Equals(DateTime.Today))) { <span style=" margin-top: 30px;margin-right: 30px;" class="pull-right"> <a href="@Url.Action("Create", "visitDates", new {id=Model.ID })" class="btn btn-default btn-primary btn-lg"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>  </a> </span> } </div> <hr /> @Html.Partial("~/Views/Pacients/visitsView.cshtml", Model)
      
      







Html .Partialコマンドヘッダー( "〜/ Views / Pacients / visitsView.cshtml"、Model)は、すべてのドキュメントのリストをロードします。 ドキュメントのリストの一番上には、動的なデータ読み込みのための一般的なJS関数があります。 VS2015はデフォルトでAngularJSをサポートしますが、このプロジェクトでは、AngularJSなしで行うことにしました-より簡単ですが、より理解しやすいです。 幸いなことに、これには4つの手順だけが必要でした。



受付タブにはすべてのデータが入学日順にソートされ、残りのタブには個々の種類のドキュメントがあります。 簡略化するために、すべてが再び異なる方法でレイアウトされます。



ビュー/ Pacients / visitsView.cshtml
 @model WebApplication2.Models.Pacient @using WebApplication2.Models <script> function Delete(controller, id) { if (confirm("     ?")) { $('#' + controller + 'Div' + id).load('/' + controller + '/pacientDelete/' + id); $('.' + controller + 'Div' + id).load('/' + controller + '/pacientDelete/' + id); } } function Cancel(controller, id) { if (confirm("  ,      . ?")) { $("#" + controller + "Tab").find('#' + controller + 'Div' + id).load('/' + controller + '/pacientCancel/' + id); $("#" + controller + "Tab").find('.' + controller + 'Div' + id).load('/' + controller + '/pacientCancel/' + id); } } function CancelEdit(controller, id) { $.get('/' + controller + '/pacientDetails/' + id, function (data) { res = $.parseHTML('<div>' + data + '</div>'); if ($(res).find('.' + controller + 'Div' + id).html() != "") { var content = $(res).find('.' + controller + 'Div' + id).html(); } else { var content = $(res).find('#' + controller + 'Div' + id).html(); } $('#' + controller + 'Div' + id).html(content); $('.' + controller + 'Div' + id).html(content); }); } function LoadEditForm(controller, id) { if ($("#" + controller + "Tab").hasClass("active")) { $("#" + controller + "Tab").find('#' + controller + 'Div' + id).load('/' + controller + '/pacientEdit/' + id); $("#" + controller + "Tab").find('.' + controller + 'Div' + id).load('/' + controller + '/pacientEdit/' + id); } else { $("#dateTab").find('#' + controller + 'Div' + id).load('/' + controller + '/pacientEdit/' + id); $("#dateTab").find('.' + controller + 'Div' + id).load('/' + controller + '/pacientEdit/' + id); } } function PostEditForm(controller, id, mce) { if (mce == true) tinyMCE.triggerSave(); $.ajax({ type: "POST", url: '/' + controller + '/pacientEdit/' + id, data: $('.' + controller + 'Edit' + id).serialize() + $('#' + controller + 'Edit' + id).serialize(), // serializes the form's elements. success: function (data) { res = $.parseHTML('<div>' + data + '</div>'); if ($(res).find('.' + controller + 'Div' + id).html() != "") { var content = $(res).find('.' + controller + 'Div' + id).html(); } else { var content = $(res).find('#' + controller + 'Div' + id).html(); } $('#' + controller + 'Div' + id).html(content); $('.' + controller + 'Div' + id).html(content); } }); } function PostCreateForm(controller, num, mce) { if (mce == true) tinyMCE.triggerSave(); $.ajax({ type: "POST", url: '/' + controller + '/Create/', data: $('#' + controller + 'Create').serialize(), // serializes the form's elements. success: function (data) { res = $.parseHTML('<div><div>' + data + '</div></div>'); $('#documentData' + num).prepend($(res).find('div').first().html()); $('#' + controller + 'Tab').find('.tabContent').prepend($(res).find('div').first().html()); $('#' + controller + 'Create').trigger('reset'); } }); } </script> <div role="tabpanel"> <ul class="nav nav-pills nav-justified"> <li role="presentation" class="active"><a href="#dateTab" aria-controls="dateTab" role="tab" data-toggle="tab"></a></li> <li role="presentation"><a href="#InfoTab" aria-controls="InfoTab" role="tab" data-toggle="tab"> </a></li> <li role="presentation"><a href="#AnamnesisTab" aria-controls="AnamnesisTab" role="tab" data-toggle="tab"></a></li> <li role="presentation"><a href="#DebutsTab" aria-controls="DebutsTab" role="tab" data-toggle="tab"></a></li> <li role="presentation"><a href="#DiagnosesTab" aria-controls="DiagnosesTab" role="tab" data-toggle="tab"></a></li> <li role="presentation"><a href="#SyndromesTab" aria-controls="SyndromesTab" role="tab" data-toggle="tab"></a></li> <li role="presentation"><a href="#ResearchesTab" aria-controls="ResearchesTab" role="tab" data-toggle="tab"></a></li> <li role="presentation"><a href="#AssigmentsTab" aria-controls="AssigmentsTab" role="tab" data-toggle="tab"></a></li> <li role="presentation"><a href="#NeurostatusTab" aria-controls="NeurostatusTab" role="tab" data-toggle="tab"></a></li> <li role="presentation"><a href="#ReviewsTab" aria-controls="ReviewsTab" role="tab" data-toggle="tab"></a></li> </ul> <div class="tab-content"> <div role="tabpanel" class="tab-pane active fade in" id="dateTab"> @if (Model.visits.Count == 0) { <div class="bs-callout bs-callout-success"> <p>     .</p> </div> } @if (Model.visits.Count != 0 && Model.visits.First().date.Equals(DateTime.Today)) { @Html.Partial("~/Views/Pacients/documentList.cshtml", new documentList { num = 1, add = true, visit = Model.visits.First() }) } @{ int num = 9; } @foreach (var visit in Model.visits) { if (visit.date.Equals(DateTime.Today)) { continue; } @Html.Partial("~/Views/Pacients/documentList.cshtml", new documentList { num = num, add = false, visit = visit }) num = num + 8; } </div> <div role="tabpanel" class="tab-pane fade" id="InfoTab"> @Html.Partial("~/Views/Pacients/PersonalData.cshtml", Model) </div> <div role="tabpanel" class="tab-pane fade" id="AnamnesisTab"> @Html.Partial("~/Views/Pacients/anamnesisList.cshtml", Model) </div> <div role="tabpanel" class="tab-pane fade" id="DebutsTab"> @Html.Partial("~/Views/Pacients/debutList.cshtml", Model) </div> <div role="tabpanel" class="tab-pane fade" id="DiagnosesTab"> @Html.Partial("~/Views/Pacients/diagnosisList.cshtml", Model) </div> <div role="tabpanel" class="tab-pane fade" id="SyndromesTab"> @Html.Partial("~/Views/Pacients/syndromList.cshtml", Model) </div> <div role="tabpanel" class="tab-pane fade" id="ResearchesTab"> @Html.Partial("~/Views/Pacients/researchList.cshtml", Model) </div> <div role="tabpanel" class="tab-pane fade" id="AssigmentsTab"> @Html.Partial("~/Views/Pacients/assigmentList.cshtml", Model) </div> <div role="tabpanel" class="tab-pane fade" id="NeurostatusTab"> @Html.Partial("~/Views/Pacients/neurostatusList.cshtml", Model) </div> <div role="tabpanel" class="tab-pane fade" id="ReviewsTab"> @Html.Partial("~/Views/Pacients/reviewList.cshtml", Model) </div> </div> </div>
      
      









例として、たとえば履歴のあるタブのビューの1つを考えます。



ビュー/ Pacient / anamnesisList.cshtml
 @model WebApplication2.Models.Pacient @using WebApplication2.Models <div class="bs-callout bs-callout-success"> <h5> </h5> <p> </p> <div class="tabContent"> @foreach (var visit in Model.visits) { foreach (var anamnes in visit.anamnesis) { @Html.Partial("~/Views/Anamnesis/pacientDetails.cshtml", anamnes) } } </div> </div>
      
      









ご存知のように、ドキュメントコントローラーでpacientDetails、pacientCreate、pacientEdit、pacientDeleteの4つの新しいメソッドを作成しました。 それらからは上記の表現を参照する必要があります。 作成する必要があります!



新しい部分ビューの追加






ビューを作成したら、それを入力します。



ビュー/アナムネシス/ pacientDetails.cshtml
 @model WebApplication2.Models.Anamnesis <div class="@String.Format("AnamnesisDiv{0}", Model.ID) row"> <div class="col-md-4"><strong> @Html.DisplayFor(model => model.type.name) </strong> </div> <div class="col-md-6"><p> @Html.DisplayFor(model => model.comments) </p> </div> <div class="col-md-2"> <button class="btn btn-success btn-sm" onclick="LoadEditForm('Anamnesis', @Model.ID)"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> </button> <button class="btn btn-danger btn-sm" onclick="Delete('Anamnesis', @Model.ID)"> <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> </button> </div> </div> <hr />
      
      







ここでは、通常の名前の代わりに、要素名を表示するためにHtml .DisplayFor(model => model.type.name)が使用されます。 これにより、モデル内で名前を指定できます(投稿の冒頭で行ったように)。



同様に、ビューを使用して既往歴を変更できます。



ビュー/アナムネシス/ pacientEdit.cshtml
 @model WebApplication2.Models.Anamnesis <form class="@String.Format("AnamnesisEdit{0}", Model.ID)"> @Html.AntiForgeryToken() @Html.HiddenFor(model => model.ID) @Html.HiddenFor(model => model.type.ID) <div class="form-horizontal"> <div class="col-md-4"> <strong> @Html.DisplayFor(model => model.type.name) </strong> </div> <div class="col-md-6"> @Html.EditorFor(model => model.comments, new { htmlAttributes = new { @class = "form-control", @placeholder = Html.DisplayNameFor(model => model.comments) } }) @Html.ValidationMessageFor(model => model.comments, "", new { @class = "text-danger" }) </div> <div class="col-md-2"> <a onclick="CancelEdit('Anamnesis', @Model.ID);" class="btn btn-warning btn-sm"><span class="glyphicon glyphicon-backward" aria-hidden="true"></span></a> <a onclick="PostEditForm('Anamnesis', @Model.ID);" class="btn btn-primary btn-sm"><span class="glyphicon glyphicon-save" aria-hidden="true"></span></a> </div> </div> </form>
      
      







備考:





しかし、新しいオブジェクトの作成はより困難です。それをディクショナリのオブジェクトに関連付ける必要があり、これは異なるモデルであり、データを持つ別のテーブルです。 可能なすべてのオプションのリストを作成フォームにドラッグする必要があります。 簡単にロードできますが、ビューに渡すことはできません。必要なパラメーターは1つだけです。モデルです。 新しいモデルを作成する必要があります...



新しいファイルModels \ viewModels.csを作成し、プレゼンテーション用にモデルのコードを追加します。 コンテキストに追加する必要はありません。



履歴を追加するモデルコード
 public class newAnamnesis { public Anamnesis anamnesis { get; set; } public int visitID { get; set; } public int? num { get; set; } public List<AnamnesisEventType> eventTypes { get; set; } }
      
      









Controllers \ AnamnesisController.csのpacientCreate関数を思い出してください。



pacientCreate-新しい履歴を追加するメソッド
 // GET: Anamnesis/Create public ActionResult pacientCreate(int visitID, int num) { newAnamnesis na = new newAnamnesis(); na.visitID = visitID; na.num = num; na.anamnesis = new Anamnesis(); na.eventTypes = db.anamnesisTypes.ToList(); return PartialView(na); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult Create(newAnamnesis data) { VisitDate visit = db.visits.Include(v => v.anamnesis).Where(v => v.ID == data.visitID).First(); if (visit == null) return RedirectToAction("Index", "Pacients"); Pacient pacient = db.pacients.Where(p => p.visits.Any(v => v.ID == data.visitID)).First(); if (pacient == null) return RedirectToAction("Index", "Pacients"); if (ModelState.IsValid) { AnamnesisEventType type = db.anamnesisTypes.Where(a => a.ID == data.anamnesis.type.ID).First(); data.anamnesis.type = type; visit.anamnesis.Add(data.anamnesis); db.SaveChanges(); return PartialView("/views/Anamnesis/pacientDetails.cshtml", data.anamnesis); } return PartialView("/views/Anamnesis/pacientCreate.cshtml", data); }
      
      







ふー、すべて準備ができたようです。 これらの操作は、他のすべての種類のドキュメントに対してのみ実行します。 ところで、理論的にはテンプレートビューを作成するなど、これを自動化できますが、Razorでこれを行うことはできません。 私が間違っている場合は修正します。



作成フォームはトリックタブにロードされます:



[レセプション]タブのDocumentList.cshtmlビューコード
 @model WebApplication2.Models.documentList @using WebApplication2.Models @{ var cl = "bs-callout-primary"; var ac = ""; } @if (Model.add == false) { cl = "bs-callout-success"; ac = ""; } <div class="bs-callout @cl"> @if (Model.add == false) { <h5> @Model.visit.date</h5> } else { <h5> </h5> } @if (Model.visit.anamnesis.Count > 0 || Model.add == true) { <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel panel-default"> <div class="panel-heading" role="tab" id="@String.Format("#documentHeading{0}", Model.num)" onclick="$('@String.Format("#document{0}", Model.num)').collapse('toogle');"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="@String.Format("#document{0}", Model.num)" aria-expanded="true" aria-controls="collapseOne"> <span class="pull-right"><small>@Model.visit.date</small></span> </a> </h4> </div> <div id="@String.Format("document{0}", Model.num)" class="panel-collapse collapse @ac" role="tabpanel" aria-labelledby="headingOne"> <div class="panel-body"> <div id="@String.Format("documentData{0}", Model.num)"> @foreach (var anamnes in Model.visit.anamnesis) { @Html.Partial("~/Views/Anamnesis/pacientDetails.cshtml", anamnes); } </div> @if (Model.add == true) { @Html.Action("pacientCreate", "Anamnesis", new { num = Model.num, visitID = Model.visit.ID}) } </div> </div> </div> </div> Model.num = Model.num + 1; } @if (Model.visit.debutes.Count > 0 || Model.add == true) { <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel panel-default"> <div class="panel-heading" role="tab" id="@String.Format("#documentHeading{0}", Model.num)" onclick="$('@String.Format("#document{0}", Model.num)').collapse('toogle');"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="@String.Format("#document{0}", Model.num)" aria-expanded="true" aria-controls="collapseOne"> <span class="pull-right"><small>@Model.visit.date</small></span> </a> </h4> </div> <div id="@String.Format("document{0}", Model.num)" class="panel-collapse collapse @ac" role="tabpanel" aria-labelledby="headingOne"> <div class="panel-body"> <div id="@String.Format("documentData{0}", Model.num)"> @foreach (var debut in Model.visit.debutes) { @Html.Partial("~/Views/Debuts/pacientDetails.cshtml", debut); } </div> @if (Model.add == true) { @Html.Action("pacientCreate", "Debuts", new { num = Model.num, visitID = Model.visit.ID }) } </div> </div> </div> </div> Model.num = Model.num + 1; } @if (Model.visit.diagnoses.Count > 0 || Model.add == true) { <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel panel-default"> <div class="panel-heading" role="tab" id="@String.Format("#documentHeading{0}", Model.num)" onclick="$('@String.Format("#document{0}", Model.num)').collapse('toogle');"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="@String.Format("#document{0}", Model.num)" aria-expanded="true" aria-controls="collapseOne"> <span class="pull-right"><small>@Model.visit.date</small></span> </a> </h4> </div> <div id="@String.Format("document{0}", Model.num)" class="panel-collapse collapse @ac" role="tabpanel" aria-labelledby="headingOne"> <div class="panel-body"> <div id="@String.Format("documentData{0}", Model.num)"> @foreach (var diagnosis in Model.visit.diagnoses) { @Html.Partial("~/Views/Diagnoses/pacientDetails.cshtml", diagnosis); } </div> @if (Model.add == true) { @Html.Action("pacientCreate", "Diagnoses", new { num = Model.num, visitID = Model.visit.ID }) } </div> </div> </div> </div> Model.num = Model.num + 1; } @if (Model.visit.syndromes.Count > 0 || Model.add == true) { <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel panel-default"> <div class="panel-heading" role="tab" id="@String.Format("#documentHeading{0}", Model.num)" onclick="$('@String.Format("#document{0}", Model.num)').collapse('toogle');"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="@String.Format("#document{0}", Model.num)" aria-expanded="true" aria-controls="collapseOne"> <span class="pull-right"><small>@Model.visit.date</small></span> </a> </h4> </div> <div id="@String.Format("document{0}", Model.num)" class="panel-collapse collapse @ac" role="tabpanel" aria-labelledby="headingOne"> <div class="panel-body"> <div id="@String.Format("documentData{0}", Model.num)"> @foreach (var syndrome in Model.visit.syndromes) { @Html.Partial("~/Views/Syndromes/pacientDetails.cshtml", syndrome); } </div> @if (Model.add == true) { @Html.Action("pacientCreate", "Syndromes", new { num = Model.num, visitID = Model.visit.ID }) } </div> </div> </div> </div> Model.num = Model.num + 1; } @if (Model.visit.researches.Count > 0 || Model.add == true) { <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel panel-default"> <div class="panel-heading" role="tab" id="@String.Format("#documentHeading{0}", Model.num)" onclick="$('@String.Format("#document{0}", Model.num)').collapse('toogle');"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="@String.Format("#document{0}", Model.num)" aria-expanded="true" aria-controls="collapseOne"> <span class="pull-right"><small>@Model.visit.date</small></span> </a> </h4> </div> <div id="@String.Format("document{0}", Model.num)" class="panel-collapse collapse @ac" role="tabpanel" aria-labelledby="headingOne"> <div class="panel-body"> <div id="@String.Format("documentData{0}", Model.num)"> @foreach (var research in Model.visit.researches) { @Html.Partial("~/Views/Researches/pacientDetails.cshtml", research); } </div> @if (Model.add == true) { @Html.Action("pacientCreate", "Researches", new { num = Model.num, visitID = Model.visit.ID }) } </div> </div> </div> </div> Model.num = Model.num + 1; } @if (Model.visit.assigments.Count > 0 || Model.add == true) { <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel panel-default"> <div class="panel-heading" role="tab" id="@String.Format("#documentHeading{0}", Model.num)" onclick="$('@String.Format("#document{0}", Model.num)').collapse('toogle');"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="@String.Format("#document{0}", Model.num)" aria-expanded="true" aria-controls="collapseOne"> <span class="pull-right"><small>@Model.visit.date</small></span> </a> </h4> </div> <div id="@String.Format("document{0}", Model.num)" class="panel-collapse collapse @ac" role="tabpanel" aria-labelledby="headingOne"> <div class="panel-body"> <div id="@String.Format("documentData{0}", Model.num)"> @foreach (var assigment in Model.visit.assigments) { @Html.Partial("~/Views/Assigments/pacientDetails.cshtml", assigment); } </div> @if (Model.add == true) { @Html.Action("pacientCreate", "Assigments", new { num = Model.num, visitID = Model.visit.ID }) } </div> </div> </div> </div> Model.num = Model.num + 1; } @if (Model.visit.neurostatuses.Count > 0 || Model.add == true) { <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel panel-default"> <div class="panel-heading" role="tab" id="@String.Format("#documentHeading{0}", Model.num)" onclick="$('@String.Format("#document{0}", Model.num)').collapse('toogle');"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="@String.Format("#document{0}", Model.num)" aria-expanded="true" aria-controls="collapseOne"> <span class="pull-right"><small>@Model.visit.date</small></span> </a> </h4> </div> <div id="@String.Format("document{0}", Model.num)" class="panel-collapse collapse @ac" role="tabpanel" aria-labelledby="headingOne"> <div class="panel-body"> <div id="@String.Format("documentData{0}", Model.num)"> @foreach (var neurostatus in Model.visit.neurostatuses) { @Html.Partial("~/Views/Neurostatus/pacientDetails.cshtml", neurostatus); } </div> @if (Model.add == true) { @Html.Action("pacientCreate", "Neurostatus", new { num = Model.num, visitID = Model.visit.ID }) } </div> </div> </div> </div> Model.num = Model.num + 1; } @if (Model.visit.reviews.Count > 0 || Model.add == true) { <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> <div class="panel panel-default"> <div class="panel-heading" role="tab" id="@String.Format("#documentHeading{0}", Model.num)" onclick="$('@String.Format("#document{0}", Model.num)').collapse('toogle');"> <h4 class="panel-title"> <a data-toggle="collapse" data-parent="#accordion" href="@String.Format("#document{0}", Model.num)" aria-expanded="true" aria-controls="collapseOne"> <span class="pull-right"><small>@Model.visit.date</small></span> </a> </h4> </div> <div id="@String.Format("document{0}", Model.num)" class="panel-collapse collapse @ac" role="tabpanel" aria-labelledby="headingOne"> <div class="panel-body"> <div id="@String.Format("documentData{0}", Model.num)"> @foreach (var review in Model.visit.reviews) { @Html.Partial("~/Views/Reviews/pacientDetails.cshtml", review); } </div> @if (Model.add == true) { @Html.Action("pacientCreate", "Reviews", new { num = Model.num, visitID = Model.visit.ID }) } </div> </div> </div> </div> Model.num = Model.num + 1; } <div class="row"> @Html.ActionLink("     ", "Delete", "VisitDates", new { id = Model.visit.ID }, new { @class = "btn btn-danger btn-sm pull-right", style = "margin-top: 10px;margin-right: 15px;" }) </div> </div>
      
      







ちなみに、彼にとっては、別のプレゼンテーションも必要でした。



その結果、次のようになりました。











サーバーに公開



FTP経由でサーバーにデプロイするには、プロジェクトをデプロイし、データベースを個別にデプロイする必要があります。これを行うには、プロジェクトを右クリックしてパブリケーションを選択します。



ダウンロードする前に、プロジェクトのルートにあるWeb.Release.Configを編集し、connectionStringを書き込んでサーバー上のデータベースに接続する必要があります。これを行う方法に関する指示は、ファイル自体にMicrosoftによって慎重に提供されています。



データベースのエクスポートは、SQL Server Management Studioを使用して手動で実行する必要がありました。



Azureを使用すると、すべてがさらにシンプルになります-スタジオ自体がデータベースを公開します。



おわりに



残念ながら、1つの記事ですべての微妙な点を説明することは非常に困難ですが、一般的なポイントを強調しようとしました。プロジェクトの完全なコードはGitHubで提供されています:https://github.com/roctbb/ICNE_EHR/



いくつかのことを正しくしなかったと思います。コメントをいただければうれしいです。



使用されたソースは、asp.netとstackoverflow.comの無数の質問でした。



All Articles