C# – Pass a simple string from controller to a view MVC3

asp.net-mvcasp.net-mvc-3cviewbag

I know this seems pretty basic, and it should be, but I cant find out where I am going wrong. (I hve read other articles with similar titles on SO, and other resources on the web but still cant figure it out), so any help would be appreciated.

I have a controller and in it I am setting a string variable. Now I don't mind if this takes the form of a property, an ActionResult, or a straight method. I just want a simple string that I can play with in the controller, and return it to the view.

Essentially what I am trying to do is list the files in a given folder. So my logic is like this:

  1. Find the current folder (partially successful)
  2. Append the path to the where the files you want to located are. i.e. if my current folder is Web\ then I will append something like "Content\CSS" if I wanted to list all the CSS files for example. (I do this because I want to allow the user to dynamically change the site by selecting the css to apply). So it would look like:

    CurrentPath += "Content\CSS"

  3. I want load the file names into an array or list

  4. I want to pass this list to my view to render in a combo box (which is on my _Layout.cshtml).

It is important to know that I am trying to view the string on the _Layout.cshtml as I cant just build another view for it. (Unless I am wrong, in that case I would appreicate any help).

At the moment I am still working on getting a simple string passed to my view in a way I can freely manipulate it like in step 2.

I started off with a separate static class and a global variable:

public static class MyTheme
{
    public static string CurrentPath = HostingEnvironment.MapPath("~");
}

In my view I had:
@Html.Label(MyProject.Web.Controllers.MyTheme.CurrentPath);

This worked but when I tried to use an if statement to determine if the string was null or empty I got errors. So my next attempts all failed.

Next I decided to bring it into a controller (in this case my BaseController) and this is when I started running into problems. Code below:

Inside BaseController Class

    public ActionResult ThemePath()
    {
        string currentPath = Server.MapPath("~");

        if (string.IsNullOrEmpty(currentPath))
        {
            currentPath = "Error!";
        }
        else
        {
            currentPath = "Our Path Is: " + currentPath;
        }

        return View(currentPath);
    }

I dont know how to access and run this from inside my _Layout.cshtml view

So next I tried a standard method inside BaseController:

    public string ThemePath()
    {
        string currentPath = Server.MapPath("~");

        if (string.IsNullOrEmpty(currentPath))
        {
            currentPath = "Error!";
        }
        else
        {
            currentPath = "Our Path Is: " + currentPath;
        }

        return currentPath;
    }

Again I don't know how to access it in the view

Finally I tried to use ViewBag and ViewData and now I am just going bonkers! So in my base controller I have:

    public string ThemePath()
    {
        ViewBag.currentPath = Server.MapPath("~");

        if (string.IsNullOrEmpty(ViewBag.currentPath))
        {
            ViewBag.currentPath = "Error!";
        }
        else
        {
            ViewBag.currentPath = "Our Path Is: " + ViewBag.currentPath;
        }

        return ViewBag.currentPath;
    }

and in my view I have

     @Html.Label(ViewBag.CurrentPath);

or even

     @Html.Label(ViewBag.CurrentPath.ToString());

With the following friendly little error messages:

CS1973: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'Label' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.

Finally I tried ViewData in the base as follows:
public string ThemePath()
{
ViewData["currentPath"] = Server.MapPath("~");

        if (string.IsNullOrEmpty(ViewData["currentPath)"].ToString()))
        {
            ViewData["currentPath"] = "Error!";
        }
        else
        {
            ViewData["currentPath"] = "Our Path Is: " + ViewData["currentPath"];
        }

        return ViewData["currentPath"].ToString();
    }

and correspondingly in the _Layout.cshtml I tried:

     @Html.Label(ViewData["CurrentPath"].ToString());

Without the .ToString() I get the above error:

With the .ToString() I get a null refrence execption error.

So I am kinda lost now and don't really know where I am going wrong. Thanks in advance for any help.

Best Answer

To pass a string to the view as the Model, you can do:

public ActionResult Index()
{
    string myString = "This is my string";
    return View((object)myString);
}

You must cast it to an object so that MVC doesn't try to load the string as the view name, but instead pass it as the model. You could also write:

return View("Index", myString);

.. which is a bit more verbose.

Then in your view, just type it as a string:

@model string

<p>Value: @Model</p>

Then you can manipulate Model how you want.

For accessing it from a Layout page, it might be better to create an HtmlExtension for this:

public static string GetThemePath(this HtmlHelper helper)
{
    return "/path-to-theme";
}

Then inside your layout page:

<p>Value: @Html.GetThemePath()</p>

Hopefully you can apply this to your own scenario.

Edit: explicit HtmlHelper code:

namespace <root app namespace>
{
    public static class Helpers
    {
        public static string GetThemePath(this HtmlHelper helper)
        {
            return System.Web.Hosting.HostingEnvironment.MapPath("~") + "/path-to-theme";
        }
    }
}

Then in your view:

@{
    var path = Html.GetThemePath();
    // .. do stuff
}

Or: <p>Path: @Html.GetThemePath()</p>

Edit 2:

As discussed, the Helper will work if you add a @using statement to the top of your view, with the namespace pointing to the one that your helper is in.