3

I am using Asp.net MVC 4 and .NET 4.5. I have a table with one column which is decimal not null value. I have created a razor view using scaffolding template of MVC for model that is created by Entity framework for that table.

Now when we enter 0 or nothing(null) on text box of decimal property, on server it is coming as 0. and after validation it displays as zero on text box.

is there any way using which we can identify whether client has entered zero or null on text box so that after post back, if any validation comes, client gets the value which he/she has posted

Update 1

public partial class Student
{
    public int StudentID { get; set; }
    public string LastName { get; set; }
    public string FirstMidName { get; set; }
    public System.DateTime EnrollmentDate { get; set; }
    public decimal RollNo { get; set; }
}

is the class that EF has generated.

and in View I have used

@Html.TextBox("Students[0].RollNo", Model.Students[0].RollNo)

in my model, this list of this class is a property.

hajirazin
  • 817
  • 8
  • 19
  • How are you trying to read the value of that text box? Is it via javascript? or are you trying to read it after you submit a form? Hard to tell what your issue is with just the code you have posted. – Gjohn Feb 12 '14 at 13:24
  • I am having html.beginfrom method of mvc. MVC's default model binder reads the values and assigns to model – hajirazin Feb 12 '14 at 14:00

4 Answers4

3

I would recommend using a custom validation attribute as descriped here: ASP.NET MVC: Custom Validation by Data Annonation

public class MyAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        int temp;

        if (!Int32.TryParse(value.ToString(), out temp))
            return false;

        return true;
    }
}

and decorate your property with [MyAttribute]

EDIT:

As the empty textbox provides a zero on empty just change your property to a nullable one double?. This should submit a null which can be separated from zero.

public partial class Student
{
    public int StudentID { get; set; }
    public string LastName { get; set; }
    public string FirstMidName { get; set; }
    public System.DateTime EnrollmentDate { get; set; }
    public decimal? RollNo { get; set; }
}

MSDN Nullable Types

Edit 2:

As you have no influencs on the model and don't want to use viewmodels and backupproperties, here's another approach : using a custom modelbinder.

public class DoubleModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (string.IsNullOrEmpty(valueResult.AttemptedValue))
        {
            return double.NaN;
        }
        return valueResult;
    }
}

 protected void Application_Start()
 {
     ModelBinders.Binders.Add(typeof(double), new DoubleModelBinder());
 }

That gives you the constant double.NaN value in your model, if the submitted value is empty. Hope this helps.

Community
  • 1
  • 1
csteinmueller
  • 2,427
  • 1
  • 21
  • 32
  • Your code will restrict zero. where as in my case 0 is allowed but submitting keeping textbox empty is not allowed – hajirazin Feb 12 '14 at 12:11
  • you could bind to a additional string property. If textbox is empty, it submits "". `Int32.TryParse` will fail. – csteinmueller Feb 12 '14 at 12:51
  • But that will make me to maintain two fields for on DB column. i.e. when ever I retrieve the data I need to assign it to back up string property and when ever I save data I need to take string value and assign it to original decimal value. That is tedious. I need some better solution. – hajirazin Feb 12 '14 at 14:04
  • But the problem is I can not change the model. It is auto generated model by entity framework – hajirazin Feb 13 '14 at 05:31
  • in my case model is not decimal, but it is List of student class where student class has one property that is decimal. I don't thing model binder of decimal will be called in this case :( – hajirazin Feb 18 '14 at 11:05
  • I tried your code. If double exist in property then also model binder is called(I never knew that. Thanks for that). But now problem is I did not find some thing similar to NaN in decimal. – hajirazin Feb 18 '14 at 11:23
  • 1
    You could define your own "invalid" value. Choose -1 or whatever and create a const field with -1. From the context I guess -1 is no valid value for `RoleNo` – csteinmueller Feb 18 '14 at 12:03
  • 1
    chose decimal.MinValue considering null and worked. Marked as answer – hajirazin Feb 19 '14 at 09:15
3

decimal not null value [...] is there any way using which we can identify whether client has entered zero or null on text box so that after post back, if any validation comes, client gets the value which he/she has posted

Yes, by using a ViewModel with a decimal property that is nullable. You shouldn't be using Entity Framework models as view models anyway.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • that's true and that works as well, But I didn't want to do conversation of model and viewmodel all the time I retrieve data and every time I save it. Hence I chose to use model directly. Any ways is there any other way through wich we can handle this? – hajirazin Feb 13 '14 at 05:33
  • 1
    @haji not that I know of. Point is your controller doesn't know the difference of a 0 that has been entered by the user and a 0 as default decimal value. This may be known in the binder, then see @csteinmueller's answer: if the value is set to `double.NaN` (a special value) is returned, the input was empty and so you don't update your record. – CodeCaster Feb 13 '14 at 08:06
  • do we have something like NaN in decimal? – hajirazin Feb 18 '14 at 11:20
  • @hajirazin [as explained in this question: no](http://stackoverflow.com/questions/986268/why-is-nan-not-a-number-only-available-for-doubles). – CodeCaster Feb 18 '14 at 11:21
  • @csteinmueller has such a nice answer and that is what exactly I wanted if it would have been supported in decimal. Now this this NaN has caused problem :( – hajirazin Feb 18 '14 at 11:29
  • @hajirazin no, you using an Entity Framework model as ViewModel caused this problem. See for example [Why should I use view models](http://stackoverflow.com/questions/4878937/why-should-i-use-view-models). – CodeCaster Feb 18 '14 at 11:30
-1

Use [Required] And [DisplayFormat] Annotation to restrict the user to put null value and format the decimal value on textbox respectively..

public partial class Student
{
    public int StudentID { get; set; }
    public string LastName { get; set; }
    public string FirstMidName { get; set; }
    public System.DateTime EnrollmentDate { get; set; }
    [Required]
    [DisplayFormat(DataFormatString = "{0:0.###}")]
    public decimal RollNo { get; set; }
}
Hasib Tarafder
  • 5,773
  • 3
  • 30
  • 44
-1

Try to do it like this:

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

put this inside form:

@using (Ajax.BeginForm("Action", "Controller",null, new AjaxOptions{})
{
   @for(int i=0;i<Model.Students.Count;i++)
   {
       @Html.TextBoxFor(c=>Model.Students[i].RollNo)
   }
       <input type="submit" value ="submit"/>
}

An now using Data-annotation on your model you can make you logic using required tag or MIN, MAX ,etc. Do't forget to make ClientValidationEnabled=true in web config and to include in your Layout jquery.unobtrusive-ajax.js. Doing like this you can prevent user from submitting form if model is not valid!

If you wan to have more Data annotation just install package DataAnnotationsExtensions. Ad you will have a lot of more useful data annotation tags. Hope this will help.

Note: *Min,Max by default are not included , you can have them using DataAnnotationsExtensions.*

Nic
  • 1,088
  • 3
  • 19
  • 43
  • I don't need min and max validation. My concern is to differentiate zero and null. – hajirazin Feb 12 '14 at 14:02
  • than this is very simple , make your element nullable . So in contrller you will receive null when this si null and 0 when this will be 0 – Nic Feb 12 '14 at 14:04
  • I don't have a control over model as it is generated by entity framework. and I can't change my DB column to nullable as it is used by other applications as well – hajirazin Feb 12 '14 at 14:05
  • This should help you because nullable decimal type will be by default not 0 , will be null!Hope this will help you. – Nic Feb 12 '14 at 14:08
  • This is not good technique to work with Domain object. Mvc is Model View controller structure , not Domain View Controller. So using MVC you can make an Model for what you need and Map your model from Domain so you don't need to make it null-able in database and after POST you will need to map your object from Model do Domain and save it to database. – Nic Feb 12 '14 at 14:10