Partial view to string

Topics: Writing modules
Jun 9, 2011 at 6:26 PM

Has anybody tried to render partial views to a string?  I'm doing some ajax stuff and running into issues.  I've done this successfully in standard mvc apps, but i'm running into trouble (i think) with the orchard view engine/locator in the code i'm using.  The code I'm trying to use is from this site: http://craftycodeblog.com/2010/05/15/asp-net-mvc-render-partial-view-to-string/  Basically I'm trying to grab a partial from my module inside of a controller action, and it's not finding it.  Thanks.

Jun 14, 2011 at 6:31 PM

Hey Luke,

I wanted to start looking at this pretty soon for my projects. It's the last piece of the puzzle in making my UI really friendly.

Originally I was experimenting with a technique similar to ASP.NET's UpdatePanel - basically using Orchard's shape wrappers to turn any shape I wanted into an AJAX zone. But it required the full page to get rendered so it could capture the relevant chunks of HTML as it went; and while it would still only send the necessary pieces back down the wire, it would still take all that time composing the page.

So I think that in most of the places I wanted to use it, I'd be much better off with a method of directly grabbing a particular shape. The problem I think you're running into is that Orchard shapes don't work exactly like regular partial views and they need extra code to wire up the themeing, template overrides, and so forth.

The place to start looking for clues is ShapeResult which gets returned from a lot of the controllers and is used to render an Orchard dynamic shape with the whole template. So I'm thinking if there's isn't already a PartialShapeResult we might need to implement one :)  Anyway if you want to get heads together on this, I need to come up with a solution pretty soon as well.

Aug 12, 2011 at 1:33 PM

Is there already an solution known for this?

Oct 9, 2012 at 7:53 PM

Is there anyone know the solution to this problem?

I found a suggestion here: http://stackoverflow.com/questions/6983372/using-findview-in-orchard. But I received an error which the view cannot be found.

My goal is to return HTML text as part of a JSON object back to the client side. For an example: {Error = false, Html = "<p>This is an example</p>"}.

If anyone knows a solution, please help. Thanks in advance

Coordinator
Oct 10, 2012 at 12:06 AM

Why does that require you use FindView?

Oct 10, 2012 at 12:38 AM
Edited Oct 10, 2012 at 12:39 AM

The Html is composed by multiple Orchard Shapes which was built by action BuildDisplay/BuildEditor. I'd like to BuildDisplay or BuildEditor a content item, render it inside the controller then pass it into a JSON object as a string, then return the JSON object to the client side. 

Any suggestions? 

Coordinator
Oct 10, 2012 at 12:52 AM

Yes, you can do exactly that, without having to use FindView. Once you have your shapes, you should be able to use an IDisplayManager to execute the shape and get an HtmlString.

Oct 10, 2012 at 1:45 AM

I really appreciate your help :). However, my code is not correctly executed.

var clauseEditView = _cms.BuildEditor(clause, "UserEdit");
                    var displayContext = new DisplayContext
                    {
                        Value = clauseEditView,
                        ViewContext = new ViewContext { HttpContext = _workContextAccessor.GetContext().HttpContext },
                        ViewDataContainer = new ViewDataContainer()
                    };
                    var clauseEditRendered = _displayManager.Execute(displayContext);
                    return Json(new { Error = false, Html = clauseEditRendered });

It returns a NullReferenceException which requires the View 

System.ArgumentNullException: Value cannot be null.
Parameter name: view
   at System.Web.Mvc.ViewContext..ctor(ControllerContext controllerContext, IView view, ViewDataDictionary viewData, TempDataDictionary tempData, TextWriter writer)
   at System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection)
   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData)
What have I done wrong? 

Coordinator
Oct 10, 2012 at 1:50 AM

I think Value should be your shape, not a view.

Oct 10, 2012 at 2:22 AM

I have updated my code and created a Shape as following:

var clauseEditView = _cms.BuildEditor(clause, "UserEdit");
                    var viewModel = Shape.SingleContentItemDisplay(clauseEditView);
                    var displayContext = new DisplayContext
                    {
                        Value = viewModel,
                        ViewContext = new ViewContext { HttpContext = _workContextAccessor.GetContext().HttpContext },
                        ViewDataContainer = new ViewDataContainer()
                    };
                    var clauseEditRendered = _displayManager.Execute(displayContext);
                    return Json(new { Error = false, Html = clauseEditRendered });

SingleContentItemDisplay.cshtml also available in the View to Display content item

So still now success with this problem :(. Any suggestions?

Coordinator
Oct 10, 2012 at 4:07 AM

What do you mean exactly by no success? Are you getting an exception? Do you have a stack trace?

Oct 10, 2012 at 2:00 PM

Sorry for getting back late. It was late in Canada since you replied

Here is the stack trace:

Orchard.Exceptions.DefaultExceptionPolicy - An unexpected exception was caught
System.ArgumentNullException: Value cannot be null.
Parameter name: view
   at System.Web.Mvc.ViewContext..ctor(ControllerContext controllerContext, IView view, ViewDataDictionary viewData, TempDataDictionary tempData, TextWriter writer)
   at System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection)
   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData)
   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model)
   at Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy.ShapeTemplateBindingStrategy.Render(ShapeDescriptor shapeDescriptor, DisplayContext displayContext, HarvestShapeInfo harvestShapeInfo, HarvestShapeHit harvestShapeHit) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Descriptors\ShapeTemplateStrategy\ShapeTemplateBindingStrategy.cs:line 134
   at Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy.ShapeTemplateBindingStrategy.<>c__DisplayClass26.<>c__DisplayClass28.<Discover>b__15(DisplayContext displayContext) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Descriptors\ShapeTemplateStrategy\ShapeTemplateBindingStrategy.cs:line 118
   at Orchard.DisplayManagement.Descriptors.ShapeAlterationBuilder.<>c__DisplayClass3.<>c__DisplayClass5.<BoundAs>b__2(DisplayContext displayContext) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Descriptors\ShapeAlterationBuilder.cs:line 55
   at Orchard.DisplayManagement.Implementation.DefaultDisplayManager.Process(ShapeBinding shapeBinding, IShape shape, DisplayContext context) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Implementation\DefaultDisplayManager.cs:line 179
   at Orchard.DisplayManagement.Implementation.DefaultDisplayManager.Execute(DisplayContext context) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Implementation\DefaultDisplayManager.cs:line 88
   at Edilex.Documents.Controllers.DocumentsController.AdaptClause(Int32 clauseVersionId, AdaptClauseStatus status)
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)

Coordinator
Oct 10, 2012 at 3:41 PM

It's your ViewContext that is not complete. In fact, I think you should be able to just let those things be injected for you rather than try to build them. Can you try to get a DisplayHelper injected into your controller, and just call ShapeExecute on it?

Oct 10, 2012 at 5:21 PM

I get a non-resolve constructor parameter exception:

[DependencyResolutionException: None of the constructors found with 'Orchard.Environment.AutofacUtil.DynamicProxy2.ConstructorFinderWrapper' on type 'Edilex.Documents.Controllers.DocumentsController' can be invoked with the available services and parameters:
Cannot resolve parameter 'Orchard.DisplayManagement.Implementation.DisplayHelper displayHelper' of constructor 'Void .ctor(Orchard.IOrchardServices, Orchard.DisplayManagement.IShapeFactory, Contrib.Taxonomies.Services.ITaxonomyService, Edilex.Clauses.Services.IRepositoryService, Edilex.Documents.Services.IExportService, Edilex.Documents.Services.IDocumentService, Edilex.Documents.Services.IDocBlockService, Edilex.Clauses.Services.IContentOrderService, Edilex.Permissions.Services.IClientService, Edilex.Clauses.Services.IClauseService, Orchard.DisplayManagement.Implementation.IDisplayManager, Orchard.IWorkContextAccessor, Orchard.DisplayManagement.IDisplayHelperFactory, Orchard.DisplayManagement.Implementation.DisplayHelper)'.]
   Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) +375
   Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters) +48
   Autofac.Core.Resolving.InstanceLookup.Execute() +48
   Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) +164
   Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) +70
   Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) +155
   Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance) +72
   Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, Object& instance) +21
   Orchard.Mvc.OrchardControllerFactory.TryResolve(WorkContext workContext, Object serviceKey, T& instance) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\Mvc\OrchardControllerFactory.cs:26
   Orchard.Mvc.OrchardControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\Mvc\OrchardControllerFactory.cs:71
   System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +74
   System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +232
   System.Web.Mvc.<>c__DisplayClass6.<BeginProcessRequest>b__2() +49
   System.Web.Mvc.<>c__DisplayClassb`1.<ProcessInApplicationTrust>b__a() +13
   System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
   System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
   System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Func`1 func) +124
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +98
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
   Orchard.Mvc.Routes.HttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\Mvc\Routes\ShellRoute.cs:140
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8970356
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184

The problem is that it cannot inject ViewContext and IViewDataContainer inside the DisplayHelper constructor

public DisplayHelper(
            IDisplayManager displayManager,
            IShapeFactory shapeFactory,
            ViewContext viewContext,
            IViewDataContainer viewDataContainer) {
            _displayManager = displayManager;
            _shapeFactory = shapeFactory;
            ViewContext = viewContext;
            ViewDataContainer = viewDataContainer;
        }

I try to re-solve it manually but the error which View parameter is null as mentioned above occur :(

 

Coordinator
Oct 10, 2012 at 5:24 PM

Ah, yes, go through IDisplayHelperFactory.

Oct 10, 2012 at 5:44 PM

The error which I receive is still:

Orchard.Exceptions.DefaultExceptionPolicy - An unexpected exception was caught
System.ArgumentNullException: Value cannot be null.
Parameter name: view
   at System.Web.Mvc.ViewContext..ctor(ControllerContext controllerContext, IView view, ViewDataDictionary viewData, TempDataDictionary tempData, TextWriter writer)
   at System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection)
   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData)
   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model)
   at Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy.ShapeTemplateBindingStrategy.Render(ShapeDescriptor shapeDescriptor, DisplayContext displayContext, HarvestShapeInfo harvestShapeInfo, HarvestShapeHit harvestShapeHit) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Descriptors\ShapeTemplateStrategy\ShapeTemplateBindingStrategy.cs:line 134
   at Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy.ShapeTemplateBindingStrategy.<>c__DisplayClass26.<>c__DisplayClass28.<Discover>b__15(DisplayContext displayContext) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Descriptors\ShapeTemplateStrategy\ShapeTemplateBindingStrategy.cs:line 118
   at Orchard.DisplayManagement.Descriptors.ShapeAlterationBuilder.<>c__DisplayClass3.<>c__DisplayClass5.<BoundAs>b__2(DisplayContext displayContext) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Descriptors\ShapeAlterationBuilder.cs:line 55
   at Orchard.DisplayManagement.Implementation.DefaultDisplayManager.Process(ShapeBinding shapeBinding, IShape shape, DisplayContext context) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Implementation\DefaultDisplayManager.cs:line 179
   at Orchard.DisplayManagement.Implementation.DefaultDisplayManager.Execute(DisplayContext context) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Implementation\DefaultDisplayManager.cs:line 88
   at Orchard.DisplayManagement.Implementation.DisplayHelper.ShapeExecute(Object shape) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Implementation\DisplayHelper.cs:line 71
   at Edilex.Documents.Controllers.DocumentsController.AdaptClause(Int32 clauseVersionId, AdaptClauseStatus status) in d:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard.Web\Modules\Edilex.Documents\Controllers\DocumentsController.cs:line 279
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)

Here is my controller:

public DocumentsController(IOrchardServices services, IShapeFactory shapeFactory, ITaxonomyService taxonomyService, IRepositoryService repositoryService, IExportService exportService, IDocumentService documentService, IDocBlockService docBlockService, IContentOrderService orderService, IClientService clientService, IClauseService clauseService, IDisplayManager displayManager, IDisplayHelperFactory displayHelperFactory, IViewEngineProvider viewEngineProvider)
        {
            Services = services;
            T = NullLocalizer.Instance;
            Shape = shapeFactory;

            _cms = Services.ContentManager;
            _exportService = exportService;
            _taxonomyService = taxonomyService;
            _repositoryService = repositoryService;
            _documentService = documentService;
            _docBlockService = docBlockService;
            _orderService = orderService;
            _clientService = clientService;
            _clauseService = clauseService;
            _displayManager = displayManager;
            _viewEngineProvider = viewEngineProvider;
            _displayHelper = displayHelperFactory.CreateHelper(new ViewContext { HttpContext = Services.WorkContext.HttpContext, Controller = this }, new ViewDataContainer());
        }

Here is the code to render the View

var clauseEditView = _cms.BuildEditor(clause, "UserEdit");
                    var viewModel = Shape.SingleContentItemDisplay(clauseEditView);
                    var clauseEditRendered = _displayHelper.ShapeExecute(viewModel);
                    return Json(new { Error = false, Html = clauseEditRendered });

It requires a View in order to render the shape. Any suggestions?

Coordinator
Oct 10, 2012 at 6:01 PM

Don't call CreateHelper from the constructor.

(and of course, you'll need a template somewhere for SingleContentItemDisplay.)

Oct 10, 2012 at 6:44 PM

I changed the code according to your suggestion to this:

var clauseEditView = _cms.BuildEditor(clause, "UserEdit");
                    _displayHelper = _displayHelperFactory.CreateHelper(new ViewContext { HttpContext = Services.WorkContext.HttpContext, Controller = this, View = Shape.SingleContentItemDisplay(), TempData = TempData }, new ViewDataContainer());
                    var clauseEditRendered = _displayHelper.ShapeExecute(clauseEditView);
                    return Json(new { Error = false, Html = clauseEditRendered });

I get this exception: 

 

Orchard.Exceptions.DefaultExceptionPolicy - An unexpected exception was caught
System.InvalidOperationException: The partial view '~/Modules/Edilex.Clauses/Views/Content.Edit-Clause.cshtml' was not found or no view engine supports the searched locations. The following locations were searched:
   at System.Web.Mvc.HtmlHelper.FindPartialView(ViewContext viewContext, String partialViewName, ViewEngineCollection viewEngineCollection)
   at System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection)
   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData)
   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model)
   at Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy.ShapeTemplateBindingStrategy.Render(ShapeDescriptor shapeDescriptor, DisplayContext displayContext, HarvestShapeInfo harvestShapeInfo, HarvestShapeHit harvestShapeHit) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Descriptors\ShapeTemplateStrategy\ShapeTemplateBindingStrategy.cs:line 134
   at Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy.ShapeTemplateBindingStrategy.<>c__DisplayClass26.<>c__DisplayClass28.<Discover>b__15(DisplayContext displayContext) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Descriptors\ShapeTemplateStrategy\ShapeTemplateBindingStrategy.cs:line 118
   at Orchard.DisplayManagement.Descriptors.ShapeAlterationBuilder.<>c__DisplayClass3.<>c__DisplayClass5.<BoundAs>b__2(DisplayContext displayContext) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Descriptors\ShapeAlterationBuilder.cs:line 55
   at Orchard.DisplayManagement.Implementation.DefaultDisplayManager.Process(ShapeBinding shapeBinding, IShape shape, DisplayContext context) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Implementation\DefaultDisplayManager.cs:line 179
   at Orchard.DisplayManagement.Implementation.DefaultDisplayManager.Execute(DisplayContext context) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Implementation\DefaultDisplayManager.cs:line 88
   at Orchard.DisplayManagement.Implementation.DisplayHelper.ShapeExecute(Object shape) in D:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard\DisplayManagement\Implementation\DisplayHelper.cs:line 71
   at Edilex.Documents.Controllers.DocumentsController.AdaptClause(Int32 clauseVersionId, AdaptClauseStatus status) in d:\Documents\Koneka\TFS\Koneka\Clients\Edilex\Edilexpert\Dev\src\Orchard.Web\Modules\Edilex.Documents\Controllers\DocumentsController.cs:line 281
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)

This time I added the Shape.SingleContentItemDisplay() into the View parameter. So it seems like recognizing the Shape. In the Editor Shape, it is composed by multiple Shapes which include Wrappers and override Layout. The Content.Edit-Clause.cshtml file exists at that location but in a different module. This file override the current Content.Edit layout. The View Engine does not support this? It works if I return a ShapeResult though. So I am still missing some thing here. Any suggestions?

 

 

 

Coordinator
Oct 10, 2012 at 8:41 PM

I don't think you need to include anything but HttpContext in CreateHelper, from the existing usage I see.

Orchard will find your view if it's in a theme. Overriding a view from another module is not recommended, and can only work if you take that other module as a dependency (in manifest).

Oct 11, 2012 at 2:44 AM

If I don't include the View parameter, it will throw a exception which saying that View is null as you can see  in the above post. My colleague override the Content.Edit layout because we want to have more zones inside this Content View. As you can see below is the content of Content.Edit-Clause.cshtml

<div id="content-scrollable" class="edit-item clause-edit">
    <div class="edit-item-primary">
        @if (Model.Header != null)
        {
            <div class="edit-item-content">
                @Display(Model.Header)
            </div>
        }
        @if (Model.Content != null) {
            <div class="clearfix autowidth-left-master">
                <div class="autowidth-left">
                    <fieldset class="horizontal" style="padding-right: 4px; margin-top: 8px;">
                        <label>@T("Content")</label>
                    </fieldset>
                </div>
                <div class="edit-item-content clause-content autowidth-right">
                    @Display(Model.Content)
                </div>
            </div>
        }
        @if (Model.TopContent != null) {
            <fieldset class="edit-item-content">
                @Display(Model.TopContent)
            </fieldset>
        }
        @if (Model.TopTags != null) {
            <fieldset class="edit-clause-tags">
                @Display(Model.TopTags)
            </fieldset>
        }
        @if (Model.MiddleContent != null) {
            <fieldset class="edit-item-content">
                @Display(Model.MiddleContent)
            </fieldset>
        }
        @if (Model.MiddleTags != null) { 
            <fieldset class="edit-clause-tags">
                @Display(Model.MiddleTags)
            </fieldset>
        }
        @if (Model.MiddleContent2 != null) {
            <fieldset class="edit-item-content">
                @Display(Model.MiddleContent2)
            </fieldset>
        }
        @if (Model.BottomTags != null) { 
            <fieldset class="edit-clause-tags">
                @Display(Model.BottomTags)
            </fieldset>
        }
        @if (Model.BottomContent != null)
        {
            <div class="edit-item-content">
                @Display(Model.BottomContent)
            </div>
        }
    </div>
    <div class="edit-item-secondary group">
        @if (Model.Actions != null)
        {
            <div class="edit-item-actions clearfix">
                @Display(Model.Actions)
            </div>
        }
        @if (Model.Sidebar != null)
        {
            <div class="edit-item-sidebar group button-field">
                @Display(Model.Sidebar)
            </div>
        }
    </div>
</div>
I have a reference to the other module inside my module.txt. So I'm not sure where the problem is. I do appreciate you help since the beginning. However, I have spent way too much time on this problem today. I will continue over the weekend, starting with a simpler view. Thanks @bertrandleroy

Coordinator
Oct 11, 2012 at 4:19 PM

Now I'm confused about what this last template has to do with the problem. I encourage you to look at the existing usage and try to spot differences with your code. I want to get to the bottom of this because there has to be an easy way to do this. Maybe I'm missing something obvious.

Nov 6, 2012 at 1:22 PM

I write the follow codes based on the suggestion from this link: http://stackoverflow.com/questions/6983372/using-findview-in-orchard

 

public class AjaxDisplayHelperService : IAjaxDisplayHelperService
    {
        private readonly IViewEngineProvider _viewEngineProvider;

        public AjaxDisplayHelperService(IEnumerable<IViewEngineProvider> viewEngineProviders)
        {
            var engineProviders = viewEngineProviders;
            _viewEngineProvider = viewEngineProviders.Where(engine => engine.GetType() == typeof(RazorViewEngineProvider)).First();
        }

        public string RenderView(ControllerBase controller, object model)
        {
            return RenderView(controller, "_AjaxDisplayRender", model);
        }

        public string RenderView(ControllerBase controller, string viewName, object model)
        {
            var paths = new List<string>(); // This can just be an empty list and it still finds it.
            paths.Add("~/Themes/Bootstrap");
            var viewEngine = _viewEngineProvider.CreateModulesViewEngine(new CreateModulesViewEngineParams { VirtualPaths = paths });
            
            var viewResult = viewEngine.FindPartialView(controller.ControllerContext, viewName, false);

            if (viewResult.View == null)
            {
                throw new Exception("Couldn't find view " + viewName);
            }

            var viewData = new ViewDataDictionary { Model = model };

            using (var sw = new StringWriter())
            {
                var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, viewData, controller.TempData, sw);
                viewResult.View.Render(viewContext, sw);

                return sw.GetStringBuilder().ToString();
            }
        }
    }

 

The problem I encountered before was that the view could not be found. For some reasons, Autofac injects WebFormViewEngineProvider into IViewEngineProvider so the file it was looking for is .ascx not .cshtml. In order to overcome that, I did this (extracted from the code above):

 

public AjaxDisplayHelperService(IEnumerable<IViewEngineProvider> viewEngineProviders)
        {
            var engineProviders = viewEngineProviders;
            _viewEngineProvider = viewEngineProviders.Where(engine => engine.GetType() == typeof(RazorViewEngineProvider)).First();
        }

Secondly, I want to render the ContentItem object without specifying the view. So I created a _AjaxDisplayRender.cshtml inside the theme Bootstrap. In order for the RazorViewEngineProvider to find that view. I added 

paths.Add("~/Themes/Bootstrap");

 

This is more like a hack to find the view inside the current active theme. Certainly there are ways to inject the theme name using Orchard Setting (I think). However, it's good enough for me at this point.

This might not be a good solution but at least it works.

Thank you bertrandleroy and the answer from StackOverflow.