ViewComponents in MVC Core and forms vs RenderAction - asp.net-mvc

I keep hearing ViewComponents replaced RenderAction in core. However the one big thing I see missing is the ability to handle forms. It would seem ViewComponents can't do this within the view component class where as RenderAction could handle this. I understand the details as to why technically this is the case however, I am using RenderAction in .NET as (what I would refer to as a real self contained component) but the migration to Core sort of scares me because RenderAction was replaced by ViewComponent yet doesn't give the same level of functionality.
I'm just curious on what my options are when I migrate to Core with RenderAction where my "components" are handling form gets/posts. Is there any real conversion for this for Core? The only option I see is to change my component view where it specifies what controller to use and have it be dynamic to get the calling controller name via:
HttpContext.Current.Request.RequestContext.RouteData.Values["controller"]
However, this now means in every place I use this "component" I need to alter the "parent" controller to have this action method and do inside it what my RenderAction component was which seems like a horrible idea.

Related

Using #Html.Partial In Sitecore

I would like to use the generic razor helper function Html.Partial to render views that have common html in them.
For instance, I have two views set up in Sitecore Payment Information.cshtml and Agent Payment Information.cshtml. These are rendered using the Sitecore rendering engine. Both of these views have very similar html in them that I would like to put in razor views not set in Sitecore and call them with #Html.Partial as appose to #Html.Sitecore().Rendering() as the latter forces me to set up a view and model in Sitecore which I am not sure is necessary.
My question is, is there anything that Sitecore does behind the scenes that makes it necessary to usethe #Html.Sitecore().Rendering() helper method instead of the #Html.Partial() helper method? Everything seems to work fine and I believe the entire view should get cached since the #Html.Partial call is nested inside either the Payment Information view or the Agent Payment information view set up in Sitecore.
Thanks in advance.
I have Html.Partial working in an MVC solution using Glass for ORM. There are two ways I've used this, one where the assumed model being passed to the partial is the same as the parent rendering and another where we create the model on the fly.
Assumes parent rendering model is passed:
#Html.Partial("~/Views/Components/MyPartialView.cshtml")
Instantiates a new model that is passed in:
#Html.Partial("~/Views/Components/Navigation/SecondaryNavigationRendering.cshtml", new SecondaryNavigation())
The parent view will need to have a mapped model in Sitecore. The secondary view does not have a mapped model in Sitecore but is typed to receive the model being passed (so in my first example that would be my IBasePage model, in my second it would be my SecondaryNavigation model).
Hope this helps.

Render Razor View inside of WCF service

It's a quite odd task to do, but I can't change the requirements. We have to write a WCF service (SOAP, not REST) and return an HTML as a property on response object.
I don't want to use:
hard-coded strings and use string.Format() to fill in some values;
t4 template as not many people can support this approach in the future;
WebForm controls as most of our developers are used to work with MVC projects.
I already know how to render some ActionResult to a string. So, ideally, I would like to be be able to create a controller, invoke some action and get an ActionResult.
For that, I created MVC application and added service.svc file to it. Service work fine - I can invoke its methods and receive results. But my problems start when I try to render Razor View. If I simply create an instance of any controller and then invoke an action, controller's property ControllerContext is null and hence View can't be rendered. I tried crafting ControllerContext on the fly, but seems like I'm missing something.
I found very similar question here, but the solution offered there didn't work for me as HttpContext.Current is null inside of wcf methods.
Does any body know how to achieve that? Or maybe somebody can sugggest other simple and flexible way to render HTML inside of WCF method?
You should also have a look at the Nancy framework (http://nancyfx.org), as their implementation of the RazorEngine is more lightweight.
I've had a fair amount of success using Nancy to generate HTML on demand - because it was designed as being inherently testable, you can abuse it to your own ends as a templating framework pretty easily.
You will need to host the Razor Engine in your app. Look at this article Rendering ASP.NET MVC Views to String, especially the section "Rendering without a ControllerContext"
Also, much more info can be found in this answer Render a view as a string. (The are several "correct" answers, with different contexts)

How Can I Hide Specific Elements on a Razor View Based on Security without Logic in View?

I have looked all over for elegant solutions to this not so age-old question. How can I lock down form elements within an ASP.Net MVC View, without adding if...then logic all over the place?
Ideally the BaseController, either from OnAuthorization, or OnResultExecultion, would check the rendering form elements and hide/not render them based on role and scope.
Another approach I have considered is writing some sort of custom attributes, so as to stay consistent with how how we lock down ActionResults with [Authorize]. Is this even possible without passing a list of hidden objects to the view and putting if's all over?
Other background info: We will have a database that will tell us at execution time (based on user role/scope) what elements will be hidden. We are using MVC3 with Razor Viewengine. We're utilizing a BaseController where any of the Controller methods can be overridden.
Any help on this would be deeply appreciated!
You could use a number of different methods:
Send the user to a different view (display only view) based on the action filter, or a condition in the controller.
On a field basis, you could build the logic into the editor templates to read custom data-annotations based on role/permission.
You can build HTML helpers to handle the logic and render the appropriate partial view, css class, or text.
For more reading:
How much logic is allowed in ASP.NET
MVC views?
ASP.NET MVC 2 Templates, Part 1: Introduction (there are 5 parts, very informative and a good place to start developing your own editor templates)

Asp.Net MVC UserControl

I'm porting an application from WebForms to MVC.
I have a WebForms UserControl that is used throughout the site and which contains presentational and business logic, and in particular some 'initizliation' logic (in the Page_Load)
My understanding of MVC UerControls is that they have no dedicated controller and thus contain no logic, and the logic is added to the controller of the viewpage to which the UserControl is added.
Now, I don;t want to have to write the initialization logic in my ViewPage, as this UserControl appears on several pages, thus duplication of logic.
I don't think I can user a MasterPage, as the UserControl can be rendered either vertically to the left of the page or hozontally at the top of the page depending on what page it is. This would require 2 MasterPage's, and again duplication of logic.
Do I have any other options?
This is a good case to use the RenderAction html helper. Much better, grab the Microsoft MVC futures and use the RenderAction method. Basically it lets you call a controller action within a view, which is alot more like how UserControls work than RenderPartial.
Bleh, I guess I should do it properly and pass in a object via my controller's viewdata rather than hacky-slash it.

Is there an equivalent to Monorail view components for the ASP.Net MVC Framework?

I make heavy use of View Components in some of the larger applications I've built in Monorail - What is the equivalent approach in ASP.Net MVC for a view component, that can support sections etc.?
Actually you have several options to create the equivalent of a ViewComponent in ASP.NET MVC, depending in the complexity of your component. I use these two approaches which are the more mvc-ish of the options I am aware of.
1:
The simplest thing is to create a ViewUserControl and display it using Html.RenderPartial with the helper. The ViewUserControl is a simple piece of markup with no backing controller (I think you can put a codebehind file if you want).
Optionally, you can pass a model object or the entire ViewData dictionary to the view when calling RenderPartial, like this:
<% Html.RenderPartial("TopBar", model); %>
"TopBar" is an ascx page. This works anywhere, in master pages and in normal views.
2:
If you want your component to have more complicated logic or to access datasources, IoC, etc, then you can use Html.RenderAction which is an extension method found in the Microsoft.Web.Mvc assembly. I am using this out of the mvccontrib distribution. It works like this, you need to create a normal controller with all the logic you need, then create some views and all of these things become your component, for example:
public class AboutComponentController : Controller {
public IRepository Repository{ get; set; }
public ActionResult Detail() {
var lastEvent = Repository.FindAll<Auditoria>().FirstOrDefault();
return View(lastEvent);
}
}
Notice how I have a reference to an IRepository which is going to be injected with IoC (Windsor in my case) and I can do anything a normal controller would do.
Now, in any page (master or normal) where you want to use your component, import Microsoft.Web.Mvc and call Html.RenderAction with the appropriate parameters. This will create a mini mvc pipeline that creates the controller, resolves the view, etc., just like a Monorail ViewComponent. I prefer to use the lambda based variation of the method, like this:
<% Html.RenderAction<AboutComponentController>(x => x.Detail("a message"));%>
Unfortunately, the only way to pass parameters is to use the method call itself, which in turn must be unique in the controller. Still needs some work to resemble a ViewComponent.
I don't use masterpages or layouts in the views of my components since they are composition elements themselves.
Remember that when using the Webforms view engine, you can have strongly typed views if you like to have intellisense when using the Model variable in code blocks.
The beauty of this is that you can mix view engines with these approaches, I usually create the components in nvelocity and display them in aspx pages, etc.
I now there can be issues with caching of the partial views but I haven't run into any so far. I am sure there are other options (like subcontrollers in mvccontrib) but this is usually enough for simple cases. Of course you can use normal ASP.net components in your aspx view pages but that would be cheating right? hehe. I hope it helps.
Phil Haack blogged about creating areas to group controllers into sub-folders/sections similar to MonoRails.

Resources