質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

Q&A

解決済

2回答

22319閲覧

ASP.Net モデルにRequiredを定義したのにエラーメッセージが表示されない

_Mar85

総合スコア13

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

0グッド

0クリップ

投稿2016/08/14 16:17

編集2016/08/17 08:22

###前提・実現したいこと
ASP.Net MVC5でWebシステムを作っています。
ユーザに必ず入力してもらいたい項目があるため、当該項目が未入力の状態ではデータを保存できないようにしたいです。

###発生している問題・エラーメッセージ
入力項目のうち、数項目は必須入力としたく、モデルにRequired属性を追加しました。(属性を定義していない項目もある。)
本来であれば、DB更新時に必須項目が未入力の場合はエラーメッセージが表示されると思うのですが、
エラーメッセージが何も表示されないまま、DB更新後に遷移させるIndex画面へ遷移してしまう。

一般的にこのような問題が発生する時に考えられる原因をご教示頂きたいです。

###試したこと
必須/非必須含め、全入力項目にデータを入力した状態にするとDB更新がされることは確認済み。
非必須項目を未入力とした場合も、DB更新がされない。Required属性を定義したのに原因不明。

###補足情報(言語/FW/ツール等のバージョンなど)
言語:C#
.NetFramework:4.5
ツール:Visual Studio2015 Community

すみません。問題を解決できないのでコードを追加しました。
例えば、項目"Price"は任意項目ですが、未入力状態でsaveしようとすると、何もエラーも表示されず、DB更新もされない状態です。
DB更新処理はEntity Framework4.5利用。
データベースはコードファーストで作成しました。

javascript

1View 2<script type="text/javascript"> 3function Quotation_save() { 4 // Step 1: Read View Data and Create JSON Object 5 6 // Creating SalesSub Json Object 7 var quotationsub = { 8 "QuotationId": "", "Line": "", "Grade": "", "Commodity": "", "Size": "", "metrictons": "", 9 "PC": "", "Price_detail": "", "Ideaprice_Offer_Bid_detail": "", "FOB_CFR_CIF_CIP_detail": "" 10 }; 11 12 13 // Creating SalesMain Json Object 14 var quotationmain = { 15 "QuotationId": "", "Customer": "", "Tender_Nontender": "", "SPOT_REPEAT": "", "TotalVolume": "", 16 "Price": "", "Ideaprice_Offer_Bid": "", "FOB_CFR_CIF_CIP": "", "PaymentTerm": "", "ShippingSchedule": "", 17 "Usage": "", "LoadingPort": "", "DischargingPort": "", "Country": "", "PreferredSupplier": "", "Remarks": "", "MailRecipient_To": "", "MailRecipient_Cc": "", "MailSender": "", "RegisterDate": "", "QuotationSubs": [] 18 }; 19 20 // Set Sales Main Value 21 quotationmain.QuotationId = $("#QuotationId").val(); 22 quotationmain.Customer = $("#Customer").val(); 23 quotationmain.Tender_Nontender = $("#Tender_Nontender").val(); 24 quotationmain.SPOT_REPEAT = $("#SPOT_REPEAT").val(); 25 quotationmain.TotalVolume = $("#TotalVolume").val(); 26 quotationmain.Price = $("#Price").val(); 27 quotationmain.Ideaprice_Offer_Bid = $("#Ideaprice_Offer_Bid").val(); 28 quotationmain.FOB_CFR_CIF_CIP = $("#FOB_CFR_CIF_CIP").val(); 29 quotationmain.PaymentTerm = $("#PaymentTerm").val(); 30 quotationmain.ShippingSchedule = $("#ShippingSchedule").val(); 31 quotationmain.Usage = $("#Usage").val(); 32 quotationmain.LoadingPort = $("#LoadingPort").val(); 33 quotationmain.DischargingPort = $("#DischargingPort").val(); 34 quotationmain.Country = $("#Country").val(); 35 quotationmain.PreferredSupplier = $("#PreferredSupplier").val(); 36 quotationmain.Remarks = $("#Remarks").val(); 37 quotationmain.MailRecipient_To = $("#MailRecipient_To").val(); 38 quotationmain.MailRecipient_Cc = $("#MailRecipient_Cc").val(); 39 quotationmain.MailSender = $("#MailSender").val(); 40 quotationmain.RegisterDate = $("#RegisterDate").val(); 41 42 43 // Getting Table Data from where we will fetch Sales Sub Record 44 var oTable = $('.tbl').dataTable().fnGetData(); 45 46 47 48 for (var i = 0; i < oTable.length; i++) 49 { 50 51 // IF This view is for edit then it will read SalesId from Hidden field 52 if ($('h2').text() == "Edit") 53 { 54 quotationsub.QuotationId = $('#QuotationId').val(); 55 } 56 else 57 { 58 quotationsub.QuotationId = 0; 59 } 60 } 61 // Step 1: Ends Here 62 63 64 // Set 2: Ajax Post 65 // Here i have used ajax post for saving/updating information 66 $.ajax({ 67 url: '/QuotationMains/Create', 68 data: JSON.stringify(quotationmain), 69 type: 'POST', 70 contentType: 'application/json;', 71 dataType: 'json', 72 success: function (result) { 73 74 if (result.Success == "1") { 75 window.location.href = "/QuotationMains/index"; 76 } 77 else { 78 alert(result.ex); 79 } 80 } 81 }); 82 83 84 } 85 86</script> 87@using (Html.BeginForm()) 88{ 89 @Html.ValidationSummary(true) 90 <fieldset> 91 <legend>Header</legend> 92 93 @if (Model != null) 94 { 95 96 <input type="hidden" id="QuotationId" name="SalesId" value="@Model.QuotationId" /> 97 } 98 99 <div class="form-horizontal"> 100 <hr /> 101 @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 102 <div class="form-group"> 103 @Html.LabelFor(model => model.Customer, htmlAttributes: new { @class = "control-label col-md-2" }) 104 <div class="col-md-10"> 105 @Html.EditorFor(model => model.Customer, new { htmlAttributes = new { @class = "form-control" } }) 106 @Html.ValidationMessageFor(model => model.Customer, "", new { @class = "text-danger" }) 107 </div> 108 </div> 109 <div class="form-group"> 110 @Html.LabelFor(model => model.TotalVolume, htmlAttributes: new { @class = "control-label col-md-2" }) 111 <div class="col-md-10"> 112 @Html.EditorFor(model => model.TotalVolume, new { htmlAttributes = new { @class = "form-control" } }) 113 @Html.ValidationMessageFor(model => model.TotalVolume, "", new { @class = "text-danger" }) 114 </div> 115 </div> 116 117 <div class="form-group"> 118 @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" }) 119 <div class="col-md-10"> 120 @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } }) 121 @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" }) 122 </div> 123 </div> 124 </div> 125 </fieldset> 126<input type="button" value="Save" onclick="Quotation_save()" /> 127}

C#

1controller 2[HttpPost] 3 public JsonResult Create(QuotationMain quotationmain) 4 { 5 try 6 { 7 if (ModelState.IsValid) 8 { 9 if (quotationmain.QuotationId > 0) 10 { 11 var CurrentquotationSUb = db.QuotationSubs.Where(p => p.QuotationId == quotationmain.QuotationId); 12 13 foreach (QuotationSub ss in CurrentquotationSUb) 14 db.QuotationSubs.Remove(ss); 15 16 foreach (QuotationSub ss in quotationmain.QuotationSubs) 17 db.QuotationSubs.Add(ss); 18 19 db.Entry(quotationmain).State = EntityState.Modified; 20 } 21 //Perform Save 22 else 23 { 24 db.QuotatinoMains.Add(quotationmain); 25 } 26 db.SaveChanges(); 27 return Json(new { Success = 1, QuotationId = quotationmain.QuotationId, ex = "" }); 28 } 29 else 30 { 31 return Json(new { Success = 1, ex = "ModelState is Invalid" }); 32 } 33 } 34 catch (Exception ex) 35 { 36 return Json(new { Success = 0, ex = ex.ToString() }); 37 } 38 39 }

C#

1model 2public class QuotationMain 3 { 4 [Key] 5 public int QuotationId { get; set; } 6 7 [Required] 8 [Display(Name = "Customer", ResourceType = typeof(Quotation3.ModelResource))] 9 public string Customer { get; set; } 10 11 [Display(Name = "TotalVolume", ResourceType = typeof(Quotation3.ModelResource))] 12 public int? TotalVolume { get; set; } 13 14 [Display(Name = "Price", ResourceType = typeof(Quotation3.ModelResource))] 15 public int? Price { get; set; } 16 17 [Required] 18 [EmailAddress] 19 [Display(Name = "MailRecipient_To", ResourceType = typeof(Quotation3.ModelResource))] 20 public string MailRecipient_To { get; set; } 21}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

DataAnnotationsを使ったValidationであれば
対象のコントローラーで

if (!ModelState.IsValid) { return View(); }

のように、DataAnnotationsのルールに反しているか否かで
対応を分けるのが普通かと思います。

DataAnnotationsに対して、DBに登録できるか否かは別問題と考えた方が良いと思います。

-- 追記 ----
ajaxでやっているんですね、ですと

@Html.ValidationSummary(true)

は使えなさそうですね。

未入力項目が"null"の場合

if (result.Success == "1") { window.location.href = "/QuotationMains/index"; }else { alert(result.ex); }

if (ModelState.IsValid)

はどういう結果でしょうか。

--追記2----
コメントの
----
Required属性を定義した項目がNullの場合、ModelState.IsValidが"false"となり、データ更新がされません。
Required属性を定義していない項目がNullの場合は、想定通りデータ更新が可能。
----
で目的の
----
当該項目が未入力の状態ではデータを保存できないようにしたいです。
----
は実現できているように思えるのですがいかがでしょうか。

他に問題点としてあげている
----
本来であれば、DB更新時に必須項目が未入力の場合はエラーメッセージが表示されると思うのですが、 エラーメッセージが何も表示されないまま、DB更新後に遷移させるIndex画面へ遷移してしまう。
----
の「DB更新後に遷移させるIndex画面へ~」に関しては

return Json(new { Success = 1, ex = "ModelState is Invalid" });

Successの値が問題かと思います

私が問題点を正確に把握できておらず、的外れでしたらご指摘ください。

--追記3----
バリデーションメッセージが表示されない点に関しては
非同期での更新なので仕方がないと思います。

フロントエンドにメッセージを表示するなら
いくつか方法があるかと思います

恐らく仰る内容のバリデーションなら
ASP.NET MVCのクライアントサイド検証を有効にすれば可能だと思います
※DataAnnotationsに沿ったエラーをフロントエンドでも出力します
http://blog.shibayan.jp/entry/20110331/1301502049
http://www.atmarkit.co.jp/fdotnet/aspnetmvc3/aspnetmvc3_04/aspnetmvc3_04_03.html

要約するとWeb.configで以下の記述があること

<configuration> <appSettings> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> </appSettings> </configuration>

フロントエンドで

<script src="~/Scripts/jquery-x.x.x.min.js"></script> <script src="~/Scripts/jquery.validate.min.js"></script> <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

の読み込みがあれば有効になります。

その状態でsubmitすると

@Html.ValidationSummary(true) @Html.ValidationMessageFor(x => x.field)

のヘルパーで表示されるHTMLにエラーが吐かれます

しかしながら、ajaxなのでsubmitするわけにもいかないと思いますので
別途、クライアントサイド検証を実行する必要があります
なので

function Quotation_save() {

の中で

if($('form').valid()) return;

とすればクライアントサイド検証が実行されます。

$('form').valid()で検証の実施
その戻り値には検証OKならtrue、NGならfalseが入ります

投稿2016/08/16 03:10

編集2016/08/18 05:59
shika358

総合スコア122

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

_Mar85

2016/08/17 08:25

ありがとうございます。 return View()をしたいのですが、JsonResultを利用しているため利用できませんでした。 デバッグ実行してみたところ、未入力項目には想定通り"null"となっており、赤字表記でもないのでルールには反していないのかなと思っています。 遅ればせながらコードも追加してみました。
_Mar85

2016/08/18 00:23

Required属性を定義した項目がNullの場合、ModelState.IsValidが"false"となり、データ更新がされません。 また、EmailAddress属性を定義した項目をメールアドレスの形式にしていない場合も、同様です。 なRequired属性を定義していない項目がNullの場合は、想定通りデータ更新が可能。(ModelState.IsValidが"true") 上記の場合、result.Success == "1"となるため、データ更新有無に関わらずIndex.Viewに遷移してしまいます。
_Mar85

2016/08/18 03:18

失礼しました。本来実施したかった必須項目の未入力チェックは出来ているように見えます。 画面遷移の件については、Successの値を変更したところ、アラートが挙がるようにはなりましたが、shika358様が仰っているajax利用の制限のためか、バリデーションメッセージが表示されません。一旦、必須入力とする項目に"*"を付与しアラート内で必須未入力であることを表示するようにしましたが、具体的にどの項目が未入力またはルールに沿っていないかを伝えるにはどのようにすべきでしょうか。
_Mar85

2016/08/18 07:41

ありがとうございます! クライアントサイド検証をすることで、想定していたエラーが表示されるようになりました。
guest

0

ソースがないので「一般的にこのような問題が発生する時に考えられる原因」だけ回答しますが、

エラーが発生しているがcatchしてその後エラーを伝搬せず、その後のコントローラの遷移処理が発生している。
とかでしょうか。

どのようにDBに保存しているかわかりませんが、保存処理にブレークポイント設定してデバッグするとか、
デバッグ中に出力ウィンドウで、例外がスローされていないか確認してみては。

必須でない項目を未入力でも登録されないのはRequire属性の設定に間違いがあるか、
空文字を数値型にキャストできないといったことかもしれません。

投稿2016/08/14 16:39

flied_onion

総合スコア2604

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

_Mar85

2016/08/16 09:07

回答ありがとうございます。 初心者なもので、空文字をキャストできていないという発想がありませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問