-1

I'm trying to check a passed variable to ensure that it is indeed of type Int. However, I keep having an error appear that tells me that the variable "year" cannot be converted from an int to a string. I'm stuck because I'm not trying to convert it over so I'm confused as to what I'm missing.

    [HttpGet("[action]")]
    [Authorize]
    public ListResult ProblemsYTD(int year = "")
    {
        var sql = "SELECT DatePart(yyyy, CLL.Call_Log_Date) as [ProblemsYear], CLL.Service as [Service], Sum((DATEDIFF(dd, CLL.Call_Log_Date, GetDate()))) as [DaysOpen] " +
                "FROM VMWareSM_Test.dbo.RV_CALL as CLL " +
                "Where CLL.IPK_Stream_Ref = '19' And DatePart(yyyy, CLL.Call_Log_Date)";

        int myInt;
        if (!int.TryParse(year, out myInt))
        {
            year = "%" + year + "%";
            sql += " = @year";
        }

        sql += " Group by CLL.Service, DatePart(yyyy, CLL.Call_Log_Date) "+
                "Order by CLL.Service DESC; "; 

        SqlParameter[] sqlParams =
        {
            new SqlParameter
            {
                ParameterName = "@year",
                Value = year,
                DbType = DbType.Int32,
                Direction = ParameterDirection.Input
            }
        };
  • 3
    You can't default an int to an empty string. – Dan Burgener Jun 29 '16 at 21:47
  • 1
    `public ListResult ProblemsYTD(int year = "")` just declare it as int and year remove the default.. I would suggest a refresher in C# basics and Types – MethodMan Jun 29 '16 at 21:49
  • 1
    There is an error since you are declaring a formal parameter (year) as an int, but assigning it a value that is a string, which is going to cause an error. – user3210251 Jun 29 '16 at 21:50
  • Also using `DatePart()` means your query will run slow, because it is not [Sargable](http://stackoverflow.com/questions/799584/what-makes-a-sql-statement-sargable). – Erik Philips Jun 29 '16 at 21:54
  • instead of using `Dynamic Sql to build your query` I would also suggest that you convert this into a Stored procedure and use SqlCommand objects etc.. to execute the query along with Parameters if and where needed.. – MethodMan Jun 29 '16 at 21:57

5 Answers5

2

Let's start from your use of the variable year. It is used as part of a where condition where also a DatePart function call is involved. Now DataPart returns an integer so you need an integer for your checks, not a string.

At this point your declaration of the method should be simple an integer without a default value or you could use a default value of zero.
You cannot use an empty string as default value for an integer. C# doesn't allow this free implicit conversions between types like an Option Strictless VB.NET

So the call should be simply

public ListResult ProblemsYTD(int year = 0)

at this point all the code that checks if the caller has passed an integer is useless because the caller cannot pass any other kind of type or value. Just integers or types that can be cast to an integer without loosing information (byte, short but not long) You declare the method to receive an integer and the compiler blocks any different type with a compilation error.

However you could add a check for a reasonable value for your year variable.
For example you could limit the upper and lower values with something like this

    if (year >= 2000 && year <= DateTime.Today.Year)
    {
        sql += " = @year";
    }

Note that you cannot concatenate a "%" symbol to an integer for the same reason that you cannot assign an empty string to an integer.

Steve
  • 213,761
  • 22
  • 232
  • 286
1

Your function should be declared like this

public ListResult ProblemsYTD(string year = "")
{
 ...
}

also year = "%" + year + "%"; make no since the % is used in LIKE statements

should be something like this :

if (int.TryParse(year, out myInt))
{
   sql += " = @" + year;
}
else 
{
   throw new Exception("Year is not in correct format");
}
Shachaf.Gortler
  • 5,655
  • 14
  • 43
  • 71
1

This line looks fishy:

public ListResult ProblemsYTD(int year = "")

You're providing an empty string ("") as the default value for year. I think you mean to have the parameter be a string when it is passed in.

public ListResult ProblemsYTD(string year = "")
Curt Toppin
  • 19
  • 1
  • 5
1

I'm trying to check a passed variable to ensure that it is indeed of type Int.

Most likely you just need to use a Route Constraint

Example Route:

routes.MapRoute(
  "Product",
  "Product/{productId}",
  new {controller="Product", action="Details"}
);

Controller:

public class ProductController : Controller
{
    public ActionResult Details(int productId)
    {
        return View();
    }
}

with the following producing an error:

/Product/blah
/Product/apple

You can add a route constraint to only route to the controller/action if it is an int:

routes.MapRoute(
  "Product",
  "Product/{productId}",
  new {controller="Product", action="Details"},
  new {productId = @"\d+" }
);

This means that your controller is not in charge of type checking (it probably shouldn't anyway) and you can create a another route to catch non-ints and display a different view accordingly.

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
0
int year = ""

You cannot set an integer variable to a string value.

howcheng
  • 2,211
  • 2
  • 17
  • 24