ASP.NET MVC to PHP Laravel Migration: Html.RenderAction Alternative - asp.net-mvc

I'm currently developing a CMS using PHP Laravel (5.4) based on an existing ASP.NET MVC version I've made in the past. Since most of the ASP.NET version is written in JS, I'm trying to reuse the most I can in the newer Laravel version I'm developing. I have already translated most of the C# code to PHP, thanks to Laravel's similarities with ASP.NET MVC architecture, this was somewhat straightforward.
Currently I'm facing a issue trying to call a controller action from within a view that will in-turn render a partial view. In the ASP.NET MVC version I've accomplished this using a Html.RenderAction helper.
ASP.NET MVC Example:
<div>
#{Html.RenderAction("Controller", "Action");}
</div>
I want know if there is any alternative to the Html.RenderAction helper that I can use to accomplish this task.
I've search the interwebs and Laravel's documentation, and from what I was able to find, View Composers seem to be closest alternative. Unfortunately, I didn't find any example that could resolve my issue.
#Farrukh suggested using View Composers and it does actually work as intended. The problem is that I will need to add a View Composer to the AppServiceProvider for every partial view I want to render.
I found another solution that allows me to call an action from a view and render a partial view:
<?php echo \App\Http\Controllers\PageController::listAll(); ?>
But this solution doesn't seem very clean.

ViewComposer behaves like a global component, all you have to do is put your business logic into a method in your Model.
e.g.
class Post extends Model {
public static function archives() {
return static::selectRaw('your query here')
->get()
->toArray();
}
}
Then goto providers/AppServiceProvider.php
add your viewcomposer code into boot method (a hook before any view loads).
e.g.
#include('layouts.sidebar')
in AppServiceProvier, boot method:
public function boot() {
view()->composer('layouts.sidebar', function($view) {
$view->with('archives', \App\Post::archives());
});
}

You can use the Service Injection:
<div>
#{Html.RenderAction("Controller", "Action");}
</div>
In Laravel would be:
#inject('Controller', 'App\Http\Controllers\HomeOrOtherController')
{!! $Controller->action() !!}.
With this you will render in the view the content of the view of the action in the controller.

Related

What is a good way to build sub views with logic in ASP.NET MVC 3

We're building a business application using Microsoft ASP.NET MVC 3.
Some views are now becoming so complex that it seems reasonable to divide them into two or more separate views, with separate controllers and models. (Reuse is another reason for wanting to build separate views.)
Which method do you recommend for achieving such separation in ASP.NET MVC?
Partial Views seems like the obvious answer, but as I see it, partial views "out of the box" has little support for separate controllers.
The best solution we've found so far is this, using the
Html.RenderAction("<view initialization action method>")
method as explained here: http://www.primaryobjects.com/CMS/Article129.aspx
This post also mentions the RenderAction method: ASP .NET MVC correct UserControl architecture
Do you see any weaknesses with this approach?
Do you recommend any better, easier ways of achieving this?
Take a "Post Detail" view. A composite view that displays both "Post Summary" and "Post Comments".
Taking the partial approach, you'd end up with:
public class PostDetailModel
{
PostSummaryModel Summary { get;set; }
PostCommentsModel Comments { get;set; }
}
and view:
<div id="post_detail">
#Html.Partial("Summary", Model.Summary)
<ul class="comment-list">
#foreach(var comment in Model.Comments)
{
<li>#Html.Partial("Comment", comment)</li>
}
</ul>
</div>
This means that the PostController.Detail method would be responsible for constructing a PostSummaryModel, constructing a PostCommentsModel and selecting which partials to use to render each.
If you then also had the following model:
public class PostListModel
{
ICollection<PostSummaryModel> Posts { get;set; }
}
You would have two actions responsible for constructing a PostSummaryModel and knowing which partial to use. If your application isn't properly structured, this might lead to duplicate data access/model mapping code. But if you delegate and abstract model construction into re-usable model factories (that could be called by both actions) you minimise this risk.
One the other hand, taking the Html.Action approach your model simply becomes:
public class PostDetailModel
{
int PostId { get;set; }
}
and view:
<div id="post_detail">
#Html.Action("Summary", new { Model.PostId })
#Html.Action("Comments", new { Model.PostId })
</div>
It can then be left up the "Summary" and "Comments" actions to construct their own model and select a view.
There is however an ever so slight performance hit in choosing the Html.Action approach because ASP.NET MVC has to go through the whole process of model-binding, executing action filters, validating, etc so you probably wouldn't use Html.Action to display items in a sufficiently long list view. But for creating a composite view it can be a really clean way to stitch together half a dozen or so existing views.
I think you should go with Action or RenderAction as Darin points out if you want to have logic in your view. However, there is a "hacky" solution that you could use and that is to implement your own IViewPageActivator. Then you could have your views implement a custom WebViewPage and inject services in this WebViewPage and they will be available to your views. To summarize:
Use Partial or RenderPartial if you only need to inject the model
Use Action or RenderAction if you have some logic in your partial view
Implement IViewPageActivator and some other stuff if you really have to
UPDATE: Also, in simple scenarios helpers might do the job for you depending on what you are trying to achieve.
Take a look at client site MVC javascript framework for controlling complex UI.
In combination with jquery templating very powerfull and an option to keep an eye on ...
Backbone.js
http://documentcloud.github.com/backbone/
Kockout.js
http://knockoutjs.com/
Knockout.js vs. Backbone.js – Part 1
http://ifandelse.com/?p=61
Knockout.js vs. Backbone.js – Part 2
http://ifandelse.com/?p=70
Html.Action and Html.RenderAction are the best way to externalize some repeating complex logic in the views that requires its own controllers and models.

ASP.NET MVC Strongly Typed Widgets

I have developed a plugin system that makes it easy to plug in new logic to an application. Now I need to provide the ability to easily add UI widgets.
There are already some good responses on how to create a portal system (like iGoogle) with ASP.NET MVC, and I'm fine about the overall concept.
My question is really about how we make strongly typed widgets.
Essentially when we set up a widget we define the controller and action names that are used to render that widget. We can use one controller action for widgets that are not strongly typed (since we just return PartialView(widgetControlName) without a model)
For widgets that are strongly typed (for example to an IList) we would need to add a new controller action (since I believe it is not possible to use Generics with ActionResult e.g. ActionResult).
The important thing is that the widget developers should not change the main application controllers. So my two thoughts are this:
Create new controllers in a separate class library
Create one partial WidgetController in the main web project and then extend this in other projects (is this even possible?) - not possible as per #mfeingold
As far as the development of the widgets (user controls) go, we can just use post build events from our extension projects to copy these into the Views/Widgets directory.
Is this a good approach. I am interested to here how others have handled this scenario.
Thanks
Ben
P.S - in case it helps, an example of how we can render widgets - without using Javascript
<%foreach (var widget in Model) {%>
<%if (widget.IsStronglyTyped) {
Html.RenderAction(widget.Action, widget.Controller);
} else {
Html.RenderPartial(widget.ControlName);
}
%>
<%} %>
For me it seems that MvcContrib's portable areas fits for developing independent widgets perfectly.
Here is an example - OpenId authentication widget.
Next week You can even watch c4mvc presentation about it.
The answer to your second question is NO. all source code for partial classes should be in the same project.
Is it possible with the templating engine to create a template for your widget type, then just call <%: Html.EditorForModel(untypedWidgetModel) %> - in theory, your template for that type would then take over and render appropriate HTML.
Or have I misunderstood how templating can work?

ASP.NET MVC ViewManager equivalent

I'm looking into ASP.NET MVC, and whether or not to make the switch. One thing that I do a heck of a lot in ASP.NET, is to render HTML on AJAX callbacks and sent back to the client. I use a generic ViewManager for rendering User Controls.
I created a sample MVC App from the templates, and was looking for the RenderUserControl method inside a Controller. I found: System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial but that doesn't seem to be what I'm looking for in this context.
Is there an equivalent to the ASP.NET ViewManager in MVC?
What you want to do is return a partial view:
public ActionResult IWillCallThisViaAjax()
{
return PartialView("MyUserControlName");
}

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.

How to create a dashboard user interface using ASP.NET MVC?

I am currently building an application using ASP.NET MVC. The data entry pages are fairly easy to code, I just make the Model for the page of the type of my business object:
namespace MyNameSpace.Web.Views.ProjectEdit
{
public partial class MyView : ViewPage<Project>
{
}
}
Where I am struggling is figuring out the best way to implement a dashboard like interface, with stand-alone parts, using ASP.NET MVC, where the Model for each part would be different? I'm assuming that each part would be an MVC user control.
Also, how could I make it so each part is testable?
I think that user controls is probably the way to go. I'm not sure what the concern is about testability. You should be able to test that your controller is providing the right view data -- since you'll have several models each of these will probably be stored in a separate view data item, rather than aggregating them in a single model. Aggregating in a single model is also possible, although probably more brittle. Each control would just need to check for a particular view data item, rather than being specific to a particular model. You could approximate the model variable on each view page by doing:
<% MyUserControlModel model = ViewData["MyUserControlModel"]
as MyUserControlModel; %>
<div id="myUserControl_dashboard" class="dashboard">
Name: <%= model.Name %><br />
Count: <%$ model.Count %>
</div>
If you need to test your view, then you're probably already using Selenium or some other web testing framework. I don't think that these would care how the page was constructed and you should be able to construct your tests pretty much like you always do.
Check out the notion is sub-controllers in MVC-Contrib http://www.codeplex.com/MVCContrib. Basically you run a full request to a partial then display that partial where you want in your existing code.
Alternatively you can check out this post: http://blog.codeville.net/2008/10/14/partial-requests-in-aspnet-mvc/
Codeplex.com has an open source project "DotNet.Highcharts". This project provides an ASP.NET control that wraps around the excellent (free for personal use) Highcharts charting library. that includes a sample MVC3 project in the downloads section.
URL: http://dotnethighcharts.codeplex.com/
I have posted an article on CodeProject.com that includes a downloadable VS2012 solution and some sample C# code. However I use a webform template in my example, not MVC. The bulk of the dashboard is done using JavaScript libraries, HTML & CSS. I have included some sample C# code to demo data retrieval in C# which in then merged with JavaScript code to render one of the many dashboard charts.

Resources