Tarek Ismail
Tarek Ismail

Reputation: 19

conversion Error from String to System.Web.Mvc.ViewResult in MVC3

Hi I am quite new on MVC and I am trying to create a simple conversion from Fahrenheit to Celsius along with its unit testing. Sorry in advance for putting all the code here.

This is my controller code:

public string Convert(double value,string option)
{
    string d;

    if(option=="1") {
        d = " To Celcius"+FahrenheitToCelsius(value).ToString();
    }
    else {
        d = " To Fahrenheit" + CelsiusToFahrenheit(value).ToString();
    }
    return "ConvertTo" + d;
}

public static double CelsiusToFahrenheit(double temperatureCelsius)
{
    double celsius = temperatureCelsius;
    return (celsius * 9 / 5) + 32;
}

public static double FahrenheitToCelsius (double temperatureFahrenheit)
{
    double fahrenheit = temperatureFahrenheit;
    return (fahrenheit - 32) * 5 / 9;
}

This is my View Page

protected void btnConvert(object sender, EventArgs e)
{
    if (DropDownList1.SelectedValue=="1"){
        double temp = TemperatureConverterController.FahrenheitToCelsius(double.Parse(TextBox1.Text));
        Literal1.Text = temp.ToString();
    }
    else{
        double temp = TemperatureConverterController.CelsiusToFahrenheit(double.Parse(TextBox1.Text));
        Literal1.Text = temp.ToString();
        Literal1.Text = temp.ToString();
    }
}

When i do this unit testing i got an error:

[TestMethod]
public void ConvertReturnsAViewResultWhenInputDataIsValid()
{
    //Arrange
    var controller = new TemperatureConverterController();

    //Act
    double x = 80;
    double y = 25;
    var result = controller.Convert(x, "1") as ViewResult;
    //    here i get this error under ViewResult //

    //Assert
    Assert.IsInstanceOfType(result, typeof(ViewResult));
}

[TestMethod]
public void ConvertAsksForAViewTemplateNamedConvert()
{
    //Arrange
    var controller = new TemperatureConverterController();
    String expectedViewTemplate = "Convert";

    //Act
    double x = 80;
    double y = 25;
    var result = controller.Convert(x, "1") as ViewResult;
    ////Assert
    Assert.AreEqual<String>(expectedViewTemplate, result.ViewName);
}

Error is:

Error   Cannot convert type 'string' to 'System.Web.Mvc.ViewResult' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion.

Upvotes: 1

Views: 3299

Answers (3)

glosrob
glosrob

Reputation: 6715

Let's go backwards for a minute here.

Controller

public class ConvertController : Controller
{
    public ActionResult Convert(MyConvertViewModel vm)
    {
        if (vm == null) { return View("convert", new MyConvertViewModel { ShowResult = false }); }

        if (vm.Option == 1)
        {
            vm.Result = FahrenheitToCelsius(vm.Input);
            vm.OptionName = "Fahrenheit To Celsius";
        }
        else
        {
            vm.Result = CelsiusToFahrenheit(vm.Input);
            vm.OptionName = "Celsius to Fahrenheit";
        }
        vm.ShowResult = true;

        //not needed, just for an example
        ViewData.Add("glosrob-example", "A value goes here!");

        return View("convert", vm);
    }

    private static double CelsiusToFahrenheit(double temperatureCelsius)
    {
        double celsius = temperatureCelsius;
        return (celsius * 9 / 5) + 32;
    }

    private static double FahrenheitToCelsius(double temperatureFahrenheit)
    {
        double fahrenheit = temperatureFahrenheit;
        return (fahrenheit - 32)*5/9;
    }
}

public class MyConvertViewModel
{
    public double Result { get; set; }
    public int Option { get; set; }
    public double Input { get; set; }
    public string OptionName { get; set; }
    public bool ShowResult { get; set; }
}

View

@model MvcApplication1.Controllers.MyConvertViewModel
@{
    ViewBag.Title = "Convert";
}
<h2>Convert</h2>

@using (Html.BeginForm("convert", "convert", FormMethod.Post))
{
 <div>
     Let's convert some temperatures!
 </div>
 <div>
     @Html.LabelFor(x => x.Input, "Temp. To Convert")
     @Html.TextBoxFor(x => x.Input)
 </div>
 <div>
     @Html.LabelFor(x => x.Option, "Convert to ")
     @Html.DropDownListFor(x => x.Option, new List<SelectListItem>
     {
         new SelectListItem {Text = "Celsius", Value = "1"},
         new SelectListItem {Text = "Fahrenheit", Value = "2"}
     })
 </div>
 <div>
     <button type="submit">Convert It!</button>
 </div>
}
@if (Model.ShowResult)
{
    <p>@Model.OptionName : @Model.Input = @Model.Result</p>
}

disclaimer: there is a lot of shortcuts there, it is only included to give you an idea of what you should have.

So the view will post back data the user chooses, to the controller action Convert

The controller in turn will return a ViewResult object, and it will be rendered using the data captured in the view model MyConvertViewModel

Now we want to test this.

So here are some of the more important properties that it seems like you need to hook into

[TestMethod]
public void Not_A_Real_Test_But_Stuff_You_Will_Want_To_Use()
{
    //arrange
    var c = new ConvertController();

    //act
    var results = c.Convert(null) as ViewResult;

    //now results is a ViewResult or null

    var theViewModelProperty = results.Model as MyConvertViewModel;
    var exampleResult = theViewModelProperty.Result;
    var exampleInput = theViewModelProperty.Input;

    //etc

    //how about the view that was returned?
    var theViewName = results.ViewName;

    //or anything you put in the ViewData
    var theViewData = results.ViewData["glosrob-example"];

    Assert.Fail("This was not a real test!");
}

Hopefully this gives you an idea of how you can test for output from a controller method.

Edit: I'm not writing all your tests for you but as an e.g.

[TestMethod]
public void Convert_Should_Return_A_MyConvertViewModel()
{
    //arrange
    var c = new Controller();

    //act
    var result = c.Convert(null) as ViewResult;

    //assert
    Assert.IsNotNull(result);
    Assert.IsInstanceOfType(result.ViewModel, typeof(MyConvertViewModel));
}

[TestMethod]
public void Convert_Should_Return_The_Correct_View()
{
    //arrange
    var c = new Controller();

    //act
    var result = c.Convert(null) as ViewResult;

    //assert
    Assert.IsNotNull(result);
    Assert.AreEqual("convert", result.ViewName);
}

Upvotes: 0

Stefano Altieri
Stefano Altieri

Reputation: 4628

In MVC the controller code should return an "ActionResult" object containing the model.

If the data you want to pass to view is simply a string use:

public ActionResult Convert()
{
    //...
    return View("your result here...");
}

You can refer to data returned by controller using the "Model" property in Views or Tests.

Upvotes: 0

Syed Salman Raza Zaidi
Syed Salman Raza Zaidi

Reputation: 2192

the problem is here

var result = controller.Convert(x, "1") as ViewResult;

your Convert method is returning string and you are casting it as ViewResult

Your convert method should looks like

public ActionResult Convert()
{
    //Make a Model class and pass it to View
    //...
    return View(model_class_object);
}

Alternatively you can make controller like this

public ActionResult Convert()
{
    ViewData["tempvalue"]=Convert(x, "1");
    //Make a Model class and pass it to View
    //...
    return View();
}

and on your View you can just print it

@ViewData["tempvalue"].ToString()

Upvotes: 2

Related Questions