2016-05-29 9 views
1

Каков наилучший способ получить currentBlock в блочном аякс-вызове?Как получить currentBlock в блочном вызове ajax без ссылки на тип страницы. [episerver 9]

[HttpGet] 
public ActionResult GetSomething() 
{ 
    var currentBlock = Get(); //how? 
    return currentBlock.SomeLabel; 
} 

(я не знаю, решение, когда блок или BlockController не знают о Page)

Я хочу сделать блоки многоразовый для любой страницы.

Спасибо.

ответ

2

Думаю, вам нужно будет передать ссылку на содержание блока, но это не так уж плохо.

Для начала, убедитесь, что ваш global.asax класс включает в себя стандартный маршрут в MVC переопределения для метода RegisterRoutes:

public class EPiServerApplication : EPiServer.Global 
{ 
    protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 
    } 

    protected override void RegisterRoutes(RouteCollection routes) 
    { 
     base.RegisterRoutes(routes); 

     routes.MapRoute(
      name: "Default", 
      url: "{controller}/{action}/{id}", 
      defaults: new { action = "Index", id = UrlParameter.Optional }); 
    } 
} 

У меня есть блок, который я использовал для тестирования некоторых вещей; он имеет свойство Title и Items - список ссылок на контент.

[ContentType(DisplayName = "Super Happy Fun Block", GUID = "b5d5c00c-dc8e-4ada-8319-20fd3474d4e7", Description = "")] 
public class SuperHappyFunBlock : BlockData 
{ 
    public virtual string Title { get; set; } 

    public virtual IList<ContentReference> Items { get; set; } 
} 

Для этого блока, я создам модель представления, которая содержит эти свойства плюс свойство ContentReference. Возможно, вы можете сделать это внутри своего файла просмотра cshtml, но это немного улучшит ваше представление.

public class SuperHappyFunModel 
{ 
    public string Title { get; set; } 

    public IList<ContentReference> Items { get; set; } 

    public ContentReference ContentLink { get; set; } 
} 

Далее провод вверх контроллер блока, чтобы использовать модель представления. Мне также понадобятся некоторые файлы javascript; они могут быть добавлены здесь через контроллер. Дополнительную информацию об этом см. В документации Episerver по телефону Client Resources.

public class SuperHappyFunBlockController : BlockController<SuperHappyFunBlock> 
{ 
    public override ActionResult Index(SuperHappyFunBlock currentBlock) 
    { 
     ClientResources.RequireScript("https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.0.min.js").AtFooter(); 
     ClientResources.RequireScript("/static/js/SuperHappyFunBlock.js").AtFooter(); 

     var model = new SuperHappyFunModel 
     { 
      Title = currentBlock.Title, 
      Items = currentBlock.Items, 
      ContentLink = (currentBlock as IContent)?.ContentLink ?? ContentReference.EmptyReference 
     }; 

     return PartialView(model); 
    } 
} 

На представлении, убедитесь, что ссылка содержание визуализируется в месте, где Javascript может найти его. Я собираюсь использовать атрибут данных, который называется data-block-id.

@model SuperHappyFunModel 

<div class="SuperHappyFunBlockController" data-block-id="@Model.ContentLink.ToString()"> 
    <p class="dynamic">Content goes here.</p> 
</div> 

Javascript файл, указанный в контроллере блока нужно будет искать для всех экземпляров блока на странице, а затем для каждого из них, сделать вызов AJAX. Имейте в виду, что если ваш блок используется на странице как свойство, то он не будет иметь ContentLink, так как свойства блока не наследуют IContent.

(function($) { 
    $('.SuperHappyFunBlockController') 
     .each(function (index, blockDiv) { 
      var $blockDiv = $(blockDiv), 
       blockId = $blockDiv.attr('data-block-id'); 
      if (!blockId) { 
       console.log('This block must be a property on a page... no block id found!'); 
       return; 
      } 
      $.ajax({ 
       method: 'GET', 
       url: '/superhappyfunblock/getsomething/' + blockId, 
       success: function (data) { 
        console.log(data); 
        $blockDiv.find('.dynamic').text(data); 
       } 
      }); 
      console.log(blockId); 
     }); 
})($); 

Наконец, последнее, что нужно сделать было бы создать метод АЯКС на контроллере. Это ожидает строковый параметр с именем «id», чтобы он соответствовал представлению MVC по умолчанию, которое мы добавили в начале. Он также будет использовать инъекцию зависимостей на контроллере, чтобы получить экземпляр IContentLoader.

public class SuperHappyFunBlockController : BlockController<SuperHappyFunBlock> 
{ 
    public override ActionResult Index(SuperHappyFunBlock currentBlock) 
    { 
     // code omitted here for brevity... 
    } 

    private readonly IContentLoader _contentLoader; 

    public SuperHappyFunBlockController(IContentLoader contentLoader) 
    { 
     _contentLoader = contentLoader; 
    } 

    public ActionResult GetSomething(string id) 
    { 
     ContentReference blockReference; 
     if (!ContentReference.TryParse(id, out blockReference)) 
      return HttpNotFound(); 

     SuperHappyFunBlock block; 
     if (!_contentLoader.TryGet(blockReference, out block)) 
      return HttpNotFound(); 

     return Content($"This is some really cool stuff for the block named {((IContent) block).Name}."); 
    } 
} 
2

Почему бы не добавить маршрут вместо этого? Таким образом, URL-адрес тот же, где используется блок? Или поместите это действие в базовый класс для всех ваших контроллеров страниц. Затем вам нужно передать ссылку в действие из представления вашего блока.

+1

Я думаю, что предложение Йохана это хорошо, но вы также можете помочь в классе ** PageRouteHelper **, чтобы получить текущий контекст страницы: http://world.episerver.com/documentation/class- библиотека /? documentId = К/8/AB460229 –