Send decimal number with commas working on c sharp

2019-07-25 15:23发布

问题:

This is my first time in this very interesting forum. I'm working on a mvc project. I have my model and inside it one decimal property for currency. Also I have its edit view in which I use Html Helper TextEditorFor. This Html Helper shows at the webpage one value from de Database but it shows it as a decimal with comma. Then, When I want to send again this edit without edditing nothing, it doesn't send anything to the Database and shows the wrong TextEditBox in which I need to change the commas for a point to be able to send this data to the Database. I hope I'd have explained it correctly :P

This is the model I have:

[Display(Name = "Hardware purchasing")]
[DataType(DataType.Currency)]
public decimal Hardware { get; set; }

And this the view

<div class="form-group ">
@Html.LabelFor(model => model.Hardware,  htmlAttributes: new { @class = "control-label col-md-2 col-xs-6" })
<div class="col-md-1 col-xs-3 ">
    @Html.EditorFor(model => model.Hardware, new { htmlAttributes = new { @class = "form-control text-center" } })
    @*@Html.ValidationMessageFor(model => model.Hardware, "", new { @class = "text-danger" })*@
</div>

I was looking for some method that let me convert this number with commas to decimal in order to sent to the database. Perhaps getting the html value in the controller and converting it, but I don't know how neither if this is the correct way. I hope you could help me. Thank you very much.

回答1:

If you are facing like this in textbox from the database

Then we need to create model for custom model binders

Model

public class DecimalModelBinder : 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
        {
            actualValue = Convert.ToDecimal(valueResult.AttemptedValue,
                CultureInfo.CurrentCulture);
        }
        catch (FormatException e)
        {
            modelState.Errors.Add(e);
        }

        bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
        return actualValue;
    }
}

After that you have to register it with globle.asax file on application start.

protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
    }

In this way you will get the Hardware field will now accept both 2200800.50 and 2,200,800.50.



回答2:

This is not an answer. I want to complete the information... First of all, thank your for your answers. My controller's name is ConsultasController and it is made from the default .net mvc code after create it with view and Entity Framework option. This the code I want to use with edit function:

public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Consulta consulta = db.Consultas.Find(id);
        if (consulta == null)
        {
            return HttpNotFound();
        }
        return View(consulta);
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "ConsultaID,Usuario,FechaEntrada,Hardware,HardwareY,Software,SoftwareY,MaterialConsultaAlta,MaterialConsultaAltaY,InstalTelefonoInternet,InstalTelefonoInternetY,AlquilerOficina,AlquilerOficinaY,MobiliarioOficina,MobiliarioOficinaY,ImagenProfesional,ImagenProfesionalY,GastosEstablVarios,GastosEstablVariosY,MaterialConsultaRenov,MaterialConsultaRenovY,HardwareRenov,HardwareRenovY,SoftwareRenov,SoftwareRenovY,Afiliaciones,AfiliacionesY,Proteccion,ProteccionY,DominioInternet,DominioInternetY,MaterialFungible,MaterialFungibleY,Formacion,FormacionY, Publicidad, PublicidadY,Imprevistos,ImprevistosY,PRL,PRLY,GastosAnualesVarios,GastosAnualesVariosY,AlquilerOficinaMensual,AlquilerOficinaMensualY,SeguridadSocial,SeguridadSocialY,SeguroMedico,SeguroMedicoY,LuzCalefaccion,LuzCalefaccionY,GestoriaLitigios,GestoriaLitigiosY,AsesoriaAveriasInf,AsesoriaAveriasInfY,AlojamientoWeb,AlojamientoWebY,TelefonoInternetMensual,TelefonoInternetMensualY,GastosMensualesVarios,GastosMensualesVariosY,DiasVacaciones,DiasFestivos,DiasImprevistos,DiasTrabajoSemana,DiasFormacion,DiasGestiones,HorasTraduccion,TrabajoProductivo,Rendimiento,PrecioPalabra,PagasAnual,IRPF,SueldoMensual,NumeroPagas,IRPFdc,SueldoMensualdt,NumeroPagasdt,TarifaCobro,RendimientoDT")] Consulta consulta)

    {
        if (ModelState.IsValid)
        {
            db.Entry(consulta).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(consulta);
    }

I have not modify anything important on it. The result at the view should appear as 123,23€, with commas separating decimals and I need that it will be translated on 133.23€ with point that's sql BD accepts. I have observe your answer, both, but I can't understand where I have to put theses each codes. Have I to made a new model o insert them into de the controller? Thank you!



回答3:

Default MVC model binder cannot parse value formatted for display. So,Probably you will end up writing your own Binder for your Model class and register in Application_Start:

public class Test
    {
        [Display(Name = "Hardware purchasing")]
        [DataType(DataType.Currency)]
        public decimal Hardware { get; set; }
    }

create a custom model binder as below :

    public class TestModelBinder : DefaultModelBinder
     {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
                var result = bindingContext.ValueProvider.GetValue("Hardware");

                if (result != null)
                {
                    decimal hardware;
                    if (Decimal.TryParse(result.AttemptedValue, NumberStyles.Currency, null, out hardware))
                    return new Test { Hardware = hardware };

                bindingContext.ModelState.AddModelError("Hardware", "Wrong amount format");
            }

            return base.BindModel(controllerContext, bindingContext);
        }
    }

register it to Application_Start() in Global.asax

ModelBinders.Binders.Add(typeof(Test), new TestModelBinder());

Just Write the ModelBinder as mentioned above and then in your controller action method.Let the framework know what model binder to use i.e. Not the default but your custom one

public ActionResult Edit([ModelBinder(typeof(TestModelBinder ))] TestModelBinder test)