Render Razor View inside of WCF service - asp.net-mvc

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)

Related

ViewComponents in MVC Core and forms vs RenderAction

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.

Working with helpers in the dotnetcore DI world

I like to have static helper classes in my apps for common plumbing stuff, like checking roles, or Razor Html helpers and stuff... but how do you do this in the DI world?
Like lets say I want an extension helper to check if a user is an admin
public static async Task<bool> IsAdmin(this ApplicationUser user)
...
if(user.IsAdmin()){...}
So pre-core I could just ignore DI and create a UserManager all inside IsAdmin do whatever I need to do. But now is there no way to get the UserManager in these helpers to just use? The only way I can see is to inject it into the Controller, then pass along into the method (which I find ugly). Then there's the issue of trying to do user.IsAdmin() in the Razor view, would I need to add the UserManager to the ViewData collection to get it into the view markup?
Am I just missing something here?
Thanks,
Steve
First of all if you just asked how to use static class with di, i would say that your question is duplicate of How to use DI inside a static Method in Asp.net Core rc1
But as i see, you have some other question?
But now is there no way to get the UserManager in these helpers to
just use?
Yes there is a way : Service Locator pattern. But it is an anti pattern (see this article) . As far as possible you should avoid to use this pattern. Also see discussion in github.
The only way I can see is to inject it into the Controller, then pass
along into the method (which I find ugly)
I think this way is better than you want. I would prefer this.
Then there's the issue of trying to do user.IsAdmin() in the Razor
view, would I need to add the UserManager to the ViewData collection
to get it into the view markup?
In Aspnet core you can inject a dependency into a view, so you don't need to use ViewData. Simply you can inject UserManager into your view and then pass it as parameter to method. Take a look at official docs
Well you are talking about a cross-cutting concern here and one way how I've seen cross cutting concerns solved in ASP.NET Core MVC is with attributes (like [Authorize] for example). Which I think is an elegant solution.
So, if I understand your question correctly I think you can solve this with an Action Filter. Damien Bod described a few days ago how to use ActionFilters: https://damienbod.com/2016/09/09/asp-net-core-action-arguments-validation-using-an-actionfilter/.
So in short, you inherit from ActionFilterAttribute and make your own curstom filter called MyCustomFilter or whatever. Have this MyCustomFilter request UserManager in its constructor via DI. Then above any action method in a controller you say:
ServiceFilter[typeof(MyCustomFilter)]
And in MyCustomFilter you ofcourse have logic to check if User is IsAdmin and then take action accordingly.
Now, I've always used Microsoft's Unity to handle cross cutting concerns via interception (you can read more about that here: https://dannyvanderkraan.wordpress.com/2015/09/30/real-world-example-of-adding-auditing-with-dependency-injections-interception/. But last time I checked there is no Unity container for asp.net core yet. But this guy has a great article about porting it to core: https://dzimchuk.net/post/bring-your-own-di-container-to-aspnet-5-unity. I would really like my Interception back! Very elegant solution to cross cutting concerns. They are working on it though: https://github.com/unitycontainer/unity/issues/66. Fingers crossed...

How to create custom controls?

Which is the best way to create custom controls in a Big Mvc application? Partials views which means a partial view for each control ? HTML Helpers? another alternative?
please find below a sample of custom control that I have in the asp web application:
protected override void Render(HtmlTextWriter writer)
{
writer.WriteLine("<div class=\"btnContainer\">");
base.Render(writer);
writer.WriteLine("</div>");
writer.WriteLine("<div class=\"clr\"></div>");
}
Partials alone aren't really "controls". They need something to drive them. In MVC 5 and previous you can use child actions to create something very similar to an ASCX control. In MVC 6+ View Components are the way to go.
You can also use an HtmlHelper extension. Really, the chief determination of which you should use boils down to whether you need external data access. If you need to query a database, hit a Web API, etc., then use child actions / view components. If you're self contained (i.e. you just want to render a bit of HTML based on some existing value you already have, then you can go with an HtmlHelper extension. However, a child action / view component still works in this scenario, as well, meaning they're much more versatile overall.

Sending a parameter to the controller in ASP MVC 2

I am writing an area for administering several subsites, almost all of the functionality will be the same across each site (add/edit/remove pages etc) and my repository on instantiation takes the SiteIdentity so all the data access methods are agnostic in relation to this. The problem I have at the moment is trying to make my action methods also agnostic.
The URL pattern I want to use is along the lines of:
"ExternalSite/{identity}/{controller}/{action}/{id}"
A naive approach is to have each action take the identity parameter, but this means having to pass this in to my repository on each action as well as include it in the ViewData for a couple of UI elements. I'd much rather have this something that happens once in the controller, such as in its constructor.
What is the best way to do this? Currently the best I can come up with is trying to find and cast identity from the RouteData dictionary but part of me feels like there should be a more elegant solution.
It sounds like you want to use OnActionExecuting or a Custom ModelBinder to do that logic each time you have a specific parameter name (also known as a RouteData dictionary key).
Creating a custom modelbinder in ASP.NET MVC
Creating an OnActionExecuting method in ASP.NET MVC, Doing Serverside tracking in ASP.NET MVC
You have access to your route values in Request.RequestContext.RouteData, so you can make base controller and public property SiteIdentity, in such case you can access it from all actions in all inherited controllers.

Asp.Net WriteSubsitution vs PartialView - the right way

I have a partial view that should not be cached in a output cached MVC view.
Usually you write non-cached content by using Response.WriteSubstitution.
The problem is that WriteSubstitution takes as a parameter a HttpResponseSubstitutionCallback callback which looks like this:
public delegate string HttpResponseSubstitutionCallback(System.Web.HttpContext context)
This is where things get complicated since there is no easy/fun way to generate the html on the fly.
You have to do a hack like this.
So the question is: Is there an easier way to make a partial view not cached ?
See Phil Haack's article on donut caching in MVC. Phil takes advantage of the existing API to create a new HtmlHelper method to provide a callback that can render the non-cached code. His supplies an anonymous method to the helper to specify the callback. To get this to work unchanged, you'll still need to have a method that renders a partial view to a string, though I think it would be easier to do in an HtmlHelper -- just look at the source for RenderPartial and RenderPartialInternal and see what changes would be needed to write it to a MemoryStream instead of the Response -- I believe it would be the same code except you'd supply your stream instead of the Response output stream, then convert your stream to a string.
It might look like this:
<%= Html.Substitute( cb => Html.RenderToString( "Partial" ) ) %>
Phil indicates that it might make it in to ASP.NET MVC 1.0, but I think it's only available in the MvcFutures assembly.
In MVC2 we can use Html.Action to easily obtain the substituted html. Yeeeeiii
But Response.WriteSubstitotion is not working anymore. Aaaahhhh

Resources