Single page design using Orchard CMS

依然范特西╮ 提交于 2019-12-31 10:53:28

问题


I have a client who want's a single page design for his site where the content for each "page" is shown/hidden using javascript as the user navigates the site.

I'm not sure on the best way to approach this using Orchard. One option would be to have the content all on a single page content item but then you lose the ability to use the navigation features of Orchard and can't let the client think about administration in terms of pages.

Does anyone have ideas or experiences on how best to set this up in Orchard CMS?


Here's the solution I used based on Bertrand's advice:

public ActionResult Display(int id)
{
     var contentItem = _contentManager.Get(id, VersionOptions.Published);
     dynamic model = _contentManager.BuildDisplay(contentItem);
     var ctx = _workContextAccessor.GetContext();
     ctx.Layout.Metadata.Alternates.Add("Layout_Null");
     return new ShapeResult(this, model);
}

I created a new module with a controller containing the action method above. The action method takes a parameter for the content part id. The _contentManager and _workContextAccessor objects are being injected into the controller. The Layout.Null.cshtml view was created exactly like Bertrand suggested.


回答1:


Here's what I would do to achieve that sort of very polished experience without sacrificing SEO, client performance and maintainability: still create the site "classically" as a set of pages, blog posts, etc., with their own URLs. It's the home page layout that should then be different and bring the contents of those other pages using Ajax calls. One method that I've been using to display the same contents as a regular content item, but from an Ajax call (so without the chrome around the content, without bringing the stylesheet in, as it's already there, etc.) is to have a separate controller action that returns the contents in a "null layout":

var ctx = _workContextAccessor.GetContext();
ctx.Layout.Metadata.Alternates.Add("Layout_Null");
return new ShapeResult(this, shape);

Then, I have a Layout.Null.cshtml file in my views that looks like this:

@{
    Model.Metadata.Wrappers.Clear();
}
@Display(Model.Content)

Clearing the wrappers removes the rendering from document.cshtml, and the template itself is only rendering one zone, Content. So what gets rendered is just the contents and nothing else. Ideal to inject from an ajax call.

Does this help?




回答2:


Following along the lines of Bertrand's solution, would it make more sense to implement this as a FilterProvider/IResultFilter? This way we don't have to handle the content retrieval logic. The example that Bertrand provided doesn't seem to work for List content items.

I've got something like this in my module that seems to work:

public class LayoutFilter : FilterProvider, IResultFilter {
    private readonly IWorkContextAccessor _wca;

    public LayoutFilter(IWorkContextAccessor wca) {
        _wca = wca;
    }

    public void OnResultExecuting(ResultExecutingContext filterContext) {
        var workContext = _wca.GetContext();
        var routeValues = filterContext.RouteData.Values;

        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest()) {
            workContext.Layout.Metadata.Alternates.Add("Layout_Null");

        }           
    }

    public void OnResultExecuted(ResultExecutedContext filterContext) {
    }        
}



回答3:


Reusing Rahul's answer with added code to answer @tuanvt's question. I'm honestly not sure what your question is but if seems like you want to access the data sent with the ajax request. If it's JSON you're sending set contentType: "application/json" on the request, JSON.stringify() it , then access it in Rahul's proposed ActionFilter by extracting it from the request stream. Hope it helps in any way.

public class LayoutFilter : FilterProvider, IResultFilter {
  private readonly IWorkContextAccessor _wca;

  public LayoutFilter(IWorkContextAccessor wca) {
        _wca = wca;
  }

  public void OnResultExecuting(ResultExecutingContext filterContext) {
      var workContext = _wca.GetContext();
      var routeValues = filterContext.RouteData.Values;

      if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest()) {
           workContext.Layout.Metadata.Alternates.Add("Layout_Null");

           if (filterContext.HttpContext.Request.ContentType.ToLower().Contains("application/json"))
           {
                var bytes = new byte[filterContext.HttpContext.Request.InputStream.Length];
               filterContext.HttpContext.Request.InputStream.Read(bytes, 0, bytes.Length);
               filterContext.HttpContext.Request.InputStream.Position = 0;
               var json = Encoding.UTF8.GetString(bytes);
               var jsonObject = JObject.Parse(json);
               // access jsonObject data from ajax request
           }
      }           
  }

  public void OnResultExecuted(ResultExecutedContext filterContext) {
  }        
}


来源:https://stackoverflow.com/questions/7621135/single-page-design-using-orchard-cms

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!