问题
I have a Repair Order Domain Model. Here are just three of its properties:
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:C}", ApplyFormatInEditMode = true)]
[DisplayName("Labor Total")]
[ScaffoldColumn(true)]
[ReadOnly(true)]
public virtual decimal LaborTotal => Labor.Sum(p => p.LineTotal);
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:C}", ApplyFormatInEditMode = true)]
[DisplayName("Parts Total")]
[ScaffoldColumn(true)]
[ReadOnly(true)]
public virtual decimal PartsTotal => RepairOrderParts.Sum(p => p.LineTotal);
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:C}", ApplyFormatInEditMode = true)]
[DisplayName("Order Total")]
[ScaffoldColumn(true)]
[ReadOnly(true)]
public virtual decimal OrderTotal => LaborTotal + PartsTotal;
After I Scaffolded the Controller and Views I modified the Edit.cshtml so It would include my three currency properties as such:
<div class="form-group">
@Html.LabelFor(model => model.LaborTotal, htmlAttributes: new {@class = "control-label col-md-2"})
<div class="col-md-10">
@Html.TextBoxFor(model => model.LaborTotal, new {@class = "form-control", @readonly = "readonly", Value = string.Format("{0:C}", Model.LaborTotal) })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.PartsTotal, htmlAttributes: new {@class = "control-label col-md-2"})
<div class="col-md-10">
@Html.TextBoxFor(model => model.PartsTotal, new {@class = "form-control", @readonly = "readonly", Value = string.Format("{0:C}", Model.PartsTotal) } )
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.OrderTotal, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.OrderTotal, new { @class = "form-control", @readonly = "readonly", Value = string.Format("{0:C}", Model.OrderTotal) } )
</div>
</div>
If I remove the Value = string.Format… part of the line. All vales display fine and I can make changes and save the record. With the Value = string.Format… left in, my values are formatted properly but I cannot save any changes. It complains all three lines are not numeric (No commas or dollar signs). I took out the Validate line but that did not help, neither did switching it to @EditorFor.
Thanks in advance,
Edit:
Working but not formatted for currency:
<div class="form-group">
<label class="control-label col-md-2" for="LaborTotal">Labor Total</label>
<div class="col-md-10">
<input class="form-control" data-val="true" data-val-number="The field Labor Total must be a number." data-val-required="The Labor Total field is required." id="LaborTotal" name="LaborTotal" readonly="readonly" type="text" value="75.00" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="PartsTotal">Parts Total</label>
<div class="col-md-10">
<input class="form-control" data-val="true" data-val-number="The field Parts Total must be a number." data-val-required="The Parts Total field is required." id="PartsTotal" name="PartsTotal" readonly="readonly" type="text" value="0" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="OrderTotal">Order Total</label>
<div class="col-md-10">
<input class="form-control" data-val="true" data-val-number="The field Order Total must be a number." data-val-required="The Order Total field is required." id="OrderTotal" name="OrderTotal" readonly="readonly" type="text" value="75.00" />
</div>
</div>
With trying to format for Currency:
<div class="form-group">
<label class="control-label col-md-2" for="LaborTotal">Labor Total</label>
<div class="col-md-10">
<input Value="$75.00" class="form-control" data-val="true" data-val-number="The field Labor Total must be a number." data-val-required="The Labor Total field is required." id="LaborTotal" name="LaborTotal" readonly="readonly" type="text" value="75.00" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="PartsTotal">Parts Total</label>
<div class="col-md-10">
<input Value="$0.00" class="form-control" data-val="true" data-val-number="The field Parts Total must be a number." data-val-required="The Parts Total field is required." id="PartsTotal" name="PartsTotal" readonly="readonly" type="text" value="0" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="OrderTotal">Order Total</label>
<div class="col-md-10">
<input Value="$75.00" class="form-control" data-val="true" data-val-number="The field Order Total must be a number." data-val-required="The Order Total field is required." id="OrderTotal" name="OrderTotal" readonly="readonly" type="text" value="75.00" />
</div>
</div>
回答1:
When you do the Value = string.Format("{0:C}", Model.LaborTotal) in the htmlAttributes, razor will execute the C# code and return the value,"$86.34", (Assuming the value of your LaborTotal property is 86.34345M)which is a string. So the markup generated by your view will be
<input value="$86.34" id="LaborTotal" name="LaborTotal" readonly="readonly" type="text">
Some other html properties are omitted
So when you post it back, The string cannot assigned to a decimal property. What you can do is to remove the currency symbol from the input field and display it in a label.
<label>$</label>
@Html.TextBoxFor(model => model.LaborTotal,
new {@class = "form-control", @readonly = "readonly",
Value = string.Format("{0:0.00}", Model.LaborTotal)})
If you still want dot net to give you the currency symbol instead of hardcoding, you may create a new view model and which has a string version of your decimal property and use it and when it is posted back, you may convert it to decimal using one of the Parse method overloads.
Also, Looks like you are using this field only for display purpose( User is not editing this value, In that case i would suggest to read the existing entity and update only the field you want to update (In this case, you do not want to update the LaborTotal).
To do that, and to avoid overposting, the best solution is to create a view model for your view
public class LabelTotalSummaryVm
{
public int Id {set;get;}
public decimal LaborTotal {set;get;}
public string SomeEditableProperty { set;get;}
}
And in your GET action
public ActionResult View(int id)
{
var vm = new LabelTotalSummaryVm { Id=id };
var e = yourDbContext.RepairOrders.FirstOrDefault(s=>s==Id);
if(e!=null)
{
vm.LaborTotal =e.LaborTotal ;
vm.SomeEditableProperty =e.SomeEditableProperty ;
}
return View(vm);
}
And in your view,
@model LabelTotalSummaryVm
@using(Html.BeginForm())
{
@Html.TextBoxFor(s=>s.SomeEditableProperty);
<label>$ @Model.LaborTotal</label>
@Html.HiddenFor(s=>s.Id)
<input type="submit" />
}
And in your post, you will update only the property you wish to update
[HttpPost]
public ActionResult View(LabelTotalSummaryVm model)
{
var e = yourDbContext.RepairOrders.FirstOrDefault(s=>s==Id);
if(e!=null)
{
vm.SomeEditableProperty =model.SomeEditableProperty ;
yourDbContext.Entry(e).State=EntityState.Modified;
yourDbContext.SaveChanges();
return RedirectToAction("SomeSuccess");
}
return View(vm);
}
来源:https://stackoverflow.com/questions/34550361/how-do-i-properly-format-a-readonly-textboxfor-value-as-currency