I have a ViewComponent
that I need to invoke twice only! How and where can I tell the invokations count?
Currently I can use a session but I dislike using session in mvc apps! How may I achieve this?
namespace Partials.Components
{
public class MyComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
Session["invoked"]=(int)Session["invoked"]+1;
var model = new{
Website="Stack Overflow",
Url="www.http://stackoverflow.com"
};
return View("_MyComponent ", model);
}
}
}
and in my view
@Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>@Session["invoked"]</span> times</span>
You can use
HttpContext.Items
which has the advantage of not using the session. These items are stored and shared per request, which would also fit your objective.In your viewComponent you can add/retrieve an item as in
this.Context.Items["MyComponentInvocationCount"]
. Whenever the count is greater than 2 you can just return an empty content withreturn Content(String.Empty)
.You can combine that with an extension method so you can get the count from outside that class:
Then you could use it in a view as follows:
If you add the above lines 3 times in a view, you will see that the third one does not add any content.
EDIT - Using ViewComponentInvoker
I have been exploring how to implement this feature adding a custom
ViewComponentInvoker
.I started by adding a new attribute that can be used to decorate ViewComponents so they are limited to a certain number of invocations per request:
You would then create your view component as usual, the only change being adding this attribute:
We can then create a custom
IViewComponentInvoker
that decorates theDefaultViewComponentInvoker
.Implementing this view component invoker looks like:
It uses some extension methods to set/get the invocation count from
HttpContext.Items
(That you could also use in your view to get the number of times a view component was invoked)The final piece is to create a new
IViewComponentInvokerFactory
replacing the default one, so it creates an instance of the new custom view component invoker instead of the default one. You also need to register it on Startup.cs:With all these pieces in place, you can use your view component 3 times and you will see how it will be rendered only twice:
I prefer this solution for a few reasons: