TempData Wrapper
Asked Answered
D

4

5

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";
Delaney answered 8/6, 2012 at 21:43 Comment(0)
V
8

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;
  }
}
Voltmer answered 8/6, 2012 at 21:48 Comment(4)
throws an error: the name 'TempData' does not exist in the current context.Delaney
Updated to a method extension for all controllers.Voltmer
this works as a controller extension (I edited some typos in your code). It would be nice to be able to store TempData somehow in the property of a static class though. If you do not see any way to do that I'll go with your suggestion. Please let me know.Delaney
Sorry the extensions of c# do not currently support properties. The other way would be to write your own BaseController with the properties you want and derive all your other controllers from this.Voltmer
B
5

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";
Bernadette answered 9/6, 2012 at 7:53 Comment(0)
H
0

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.

Holliehollifield answered 9/6, 2012 at 6:12 Comment(0)
S
0

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.

Stackhouse answered 9/6, 2012 at 7:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.