Question

Because I use same keys for TempData over and over again, I would like to make it easier to keep track of these keys. It would be great if eventually I could write something like this:

MyTempData.Message = "my message";

instead of

TempData["Message"] = "my message";
Was it helpful?

Solution

Sounds like you want a strongly typed TempData. One way to go about that is writing a Extension Method on Controller to do it:

public static class ControllerExtensions
{
  public string GetMessage(this Controller instance)
  {
    string result = instance.TempData["Message"] as string;
    if (result == null)
    {
      result = "some default value or throw null argument exception";  
    }
    return result;
  }

  public void SetMessage(this Controller instance, string value)
  {
    instance.TempData["Message"] = value;
  }
}

OTHER TIPS

Pretty low-tech option, but if you just want to track the keys you're using, you could just create some constants:

public static class TempDataKeys
{
    public const string Message = "Message";
    public const string Warning = "Warning";
    public const string Error = "Error";
    // etc
}

then:

TempData[TempDataKeys.Message] = "Some message";

It's tough to tell on what level you'd like the temporary data to persist. My interpretation is that it sounds like you'd like to be able to have a shared set of properties available on all of your ViewModels.

To accomplish this, inherit from a common ViewModel class.

public class BaseViewModel
{
   public string Message{get;set;}
}

public class MyModel : BaseViewModel
{
   public string MyUniquePropety{get;set;}
}

If it turns out that you'd like data to persist in session, then implement a singleton, and remember to add a @using statement to your view to reference it.

You could mimic what ViewBag does.

First, it uses an internal sealed class called DynamicViewDataDictionary. Basically, I'm just going to make a version of that for TempData. Then, we can use extension methods to make it available in Controller, WebViewPage, etc.

public sealed class DynamicTempDataDictionary : DynamicObject
{
    private readonly Func<TempDataDictionary> _tempDataThunk;

    public DynamicTempDataDictionary(Func<TempDataDictionary> viewDataThunk)
    {
        _tempDataThunk = viewDataThunk;
    }

    private TempDataDictionary ViewData
    {
        get { return _tempDataThunk(); }
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return ViewData.Keys;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = ViewData[binder.Name];
        return true;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        ViewData[binder.Name] = value;
        return true;
    }
}

public static class TempBagExtensions
{
    private const string TempBagKey = "__CurrentTempBagDictionary";

    public static dynamic TempBag(this ControllerBase controller)
    {
        return GetCurrentDictionary(controller.ControllerContext);
    }

    public static dynamic TempBag(this WebViewPage viewPage)
    {
        return GetCurrentDictionary(viewPage.ViewContext.Controller.ControllerContext);
    }


    private static DynamicTempDataDictionary GetCurrentDictionary(ControllerContext context)
    {
        var dictionary = context.HttpContext.Items[TempBagKey] as DynamicTempDataDictionary;

        if (dictionary == null)
        {
            dictionary = new DynamicTempDataDictionary(() => context.Controller.TempData);
            context.HttpContext.Items[TempBagKey] = dictionary;
        }

        return dictionary;
    }
}

In your controller:

this.TempBag().SomeValue = "Test";

In your razor view:

@this.TempBag().SomeValue

If you don't think the extension method is clean enough, you could create your own Controller base class, as well as your own base classes for razor views that use nice, concise properties ala ViewBag.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top