4

I've got an MVC user control with the following basic structure:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Decimal>" %>

<%= Math.Round(Model) %>

Which gives this error message when I use it:

Compiler Error Message: CS0452: The type 'decimal' must be a reference type in order to use it as parameter 'TModel' in the generic type or method 'System.Web.Mvc.ViewUserControl'

Is there a way to get this to work (somehow tricking the framework into treating the Decimal as a reference type maybe?) Or is what I'm trying to do just fundamentally wrong?

kristian
  • 22,731
  • 8
  • 50
  • 78

7 Answers7

8

I would suggest you wrap the value type within a ViewModel. This will allow for some flexibility in the future (which may or may not be needed).

public class MyUserControlViewModel
{
    public Decimal MyValue { get; private set; }

    public MyUserControlViewModel(Decimal dec)
    {
        MyValue = dec;
    }
}


<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MyUserControlViewModel>" %>

<%= Math.Round(Model.MyValue) %>
Jon Erickson
  • 112,242
  • 44
  • 136
  • 174
5

Don't have to wrap into class, if you want a fast way, use this

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Nullable<Decimal>>" %>

also you can consider use

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>

and validate by code

user543518
  • 51
  • 1
  • 2
3

ViewUserControl is declared as follows:

public class ViewUserControl<TModel> : ViewUserControl
where TModel : class

So you can't trick it into compiling with a value type. I'd recommend wrapping your Decimal object in another class.

John G
  • 3,483
  • 1
  • 23
  • 12
2

You can wrap the value in a class:

 public class Wrapper
{
        public Wrapper(decimal d)
        {
            this.Value = d;   
        }
        Decimal Value { get; set; }
}

In the View:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Wrapper>" %>
<%= Math.Round(Model.Value) %>
1

The model is a DTO from the controller to the view. You should create your own DTO even with a single decimal property. The view's responsibility is only about rendering, the Math.Round should be executed by the controller.

Andrea Balducci
  • 2,834
  • 1
  • 21
  • 18
0

I'm not terribly familiar with the ASP.Net MVC Framework, but the error is saying your model has to be a class, not a primitive type, which is pretty standard from a model view controller perspective.

To get this to work, you'd need a class like:

class MyDouble : Model   // or whatever MVC calls it's Model
{
   public TheValue {
     get;
     set;
   }
}

and then replace your line with <%= Math.Round(Model.TheValue) %>.

Note, It seems like a strange design to have a custom control for just a double value. If this is just a sample app, then fine, but otherwise, you may want to reconsider how to best use custom controls.

Tim Hoolihan
  • 12,316
  • 3
  • 41
  • 54
0

While I strongly support all the answers above, stating to wrap the decimal value in a class to support further development you can quickly solve your problem by making the decimal nullable ("decimal?") since System.Nullable is a reference type.

Andrei Rînea
  • 20,288
  • 17
  • 117
  • 166