2016-09-23 5 views
0

ASP.NET MVC Core Code Firstプロジェクトでは、正常に表示されているfloat型のSaleAmountというプロパティを持つモデルがありますこのプロパティを使用してデータを保存すると、SQL Serverデータベースでこのフィールドがnullとして取得されます。デバッグモードで、私はこの行にブレークポイントを配置するときoAnnualSales.SaleAmount = item.SaleAmount;コントローラ(下に表示)私はitem.SaleAmountがnullであることがわかります。ASP.NET MVCモデルで表示モードとデータ保存の両方で通貨フォーマットを使用する方法

ビュー

public class AnnualSale 
{ @model IList<MyProj.Models.SaleViewModel> 
<div class="row"> 
    <div class="col-md-9"> 
     <form asp-controller="DbRelated" asp-action="UpdateSales" asp-route-returnurl="@ViewData[" ReturnUrl"]" method="post"> 
      <table class="table"> 
       <thead> 
        <tr> 
         <th></th> 
         <th> 
          State Name 
         </th> 
         <th> 
          Sale Amount 
         </th> 
        </tr> 
       </thead> 
       <tbody> 
        @for (int i = 0; i < Model.Count(); i++) 
        { 
        <tr> 
         <td>@Html.HiddenFor(r => r[i].StateId)</td> 
         <td> 
          @Html.EditorFor(r => r[i].StateName) 
         </td> 
         <td> 
          @Html.EditorFor(r => r[i].SaleAmount) 
         </td> 
        </tr> 
        } 
       </tbody> 
      </table> 
      <button type="submit" class="btn btn-default">Save</button> 
     </form> 
    </div> 
</div> 
    [Key] 
    public int Sale_Id { get; set; } 
    public int? FiscalYear { get; set; } 

    [DisplayFormat(DataFormatString = "{0:C0}", ApplyFormatInEditMode = true)] 
    public float? SaleAmount { get; set; } 

    public int StateId { get; set; } 
    public StateName StateName { get; set; } 
} 

モデル

public class AnnualGrant 
{ 
    [Key] 
    public int Sale_Id { get; set; } 

    public int? FiscalYear { get; set; } 

    [DisplayFormat(DataFormatString = "{0:C0}", ApplyFormatInEditMode = true)] 
    public float? SaleAmount { get; set; } 

    public int StateId { get; set; } 
    public StateName StateName { get; set; } 
} 

コントローラー

[HttpPost] 
[ValidateAntiForgeryToken] 
public async Task<IActionResult> UpdateSales(List<SaleViewModel> model, string returnUrl = null) 
{ 
    if (ModelState.IsValid) 
    { 
     foreach (var item in model) 
     { 
      var oAnnualSales = _context.AnnualSales.Where(r => r.StateId.Equals(item.StateId)).FirstOrDefault(); 
      if (oAnnualSales != null) 
      { 
       oAnnualSales.FiscalYear = item.FY; 
       oAnnualSales.SaleAmount = item.SaleAmount; 
      } 
      else 
      { 
       AnnualSale oAnnualSaleNew = new AnnualSale { StateId = item.StateId, FiscalYear = item.FY, SaleAmount = item.SaleAmount}; 
       _context.Add(oAnnualSaleNew); 
      } 
     } 
     await _context.SaveChangesAsync(); 
     return View(model); 
    } 

    // If we got this far, something failed, redisplay form 
    return View(); 
} 
+0

I:

public class FloatModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); ModelState modelState = new ModelState { Value = valueResult }; object actualValue = null; try { if (bindingContext.ModelMetadata.EditFormatString.StartsWith("{0:c", StringComparison.InvariantCultureIgnoreCase)) { actualValue = float.Parse(valueResult.AttemptedValue, NumberStyles.Currency); } else { actualValue = float.Parse(valueResult.AttemptedValue, CultureInfo.CurrentCulture); } } catch (FormatException e) { modelState.Errors.Add(e); } bindingContext.ModelState.Add(bindingContext.ModelName, modelState); return actualValue; } } 

が次にあなたがApplication_Startメソッドにそれを追加することによって、MVCバインダーにこれを追加する必要がありますすでにあなたの[前の質問](http://stackoverflow.com/questions/39600688/data-annotation-for-currency-format-not-working)で説明しました。 '' $ 1,000.00 ''という値を投稿すると、 'DefaultModelBinder'によって' float'に束縛されません( '' "1000.00"の値だけが束縛されます)。カスタムのModelBinderを作成する必要があります –

答えて

0

yにコメントで述べたように私たちの質問、通貨記号などの文字を値付きで転記すると浮動小数点数は解析されません。したがって、nullに戻ります。あなたは0を返すfloat.TryParseを使ったクイックユニットテストやコンソールアプリケーションを書いてテストすることができます。値を文字列に変更する(推奨しません)か、通貨の種類と量を(推奨)する必要があります異なる特性として。通貨記号をその金額とともに転記することは、通貨記号を入力することにも依存します。これは起こりそうもありません。

+0

私が使用しているフォーマットは '$ 15,481'のようなものです。したがって、$のための別のプロパティを作成するだけでは機能しない可能性があります。 – nam

+0

一度サーバーに投稿すると、どのように値を格納していますか?それがdatabaaeの場合、どのデータ型ですか? –

+0

'_context.SaveChangesAsync();'行の前のコントローラの 'item.SaleAmount'のブレークポイントで値をチェックすると値はnullです。したがって、Dbでもnullです。しかし、15481と入力して投稿してからページを開くと(GETメソッド)、それを表示すると$ 15,481と表示されます。 DbのDataTypeは 'real'です。 SQL Serverは2014年のEXPRESSです。 – nam

0

これはASP.NET MVCではデフォルトではサポートされていませんが、カスタムモデルバインダーで対処できます。

あなたバインディングカスタムモデルのための新しいクラスを作成するための最初の必要性:

protected void Application_Start() 
{ 
    ModelBinders.Binders.Add(typeof(float?), new FloatModelBinder());  
} 
+0

あなたのクラスはASP.NET Core MVCでは動作しません。私はASP.NET Core 1.0とVisual Studio 2015の最新バージョンを使用しています。エラーのいくつかは次のとおりです: '型または名前空間の名前' ModelState 'を見つけることができませんでした。'、 'StringComparison'に 'InvariantCultureIgnoreCase ''と 'ValueProviderResult'に 'AttemptedValue''の定義が含まれていません – nam

+0

私の悪いですが、私はそれをASP.NET Core MVCと読みませんでした。参照のために、Coreのカスタムモデルバインディングを使用して同様のテクニックを使用できます。 http://intellitect.com/custom-model-binding-in-asp-net-core-1-0/ –

関連する問題