Angular (HTML5) с DotNet (переписать конфигурацию), для Seo, чтение всего URL

0

Я использую angularJS и С#. Из-за моего превосходного спроса я должен использовать режим HTML5 любой ценой, означая знак "#". И снова сделайте по его просьбе, я использовал rewrite, чтобы обеспечить возможность доступа к угловой странице даже при обновлении страницы. В последнее время мы внедряем phantomJS, первая страница работала хорошо, пока я не заметил, что другая страница не работает, после ввода кода в коде, я узнал, что нет, он не будет захватывать весь URL-адрес, например, для: http://localhost:xyzw/flights?_escaped_fragment_= он захватывает только http://localhost:1350/?_escaped_fragment_=, который не содержит часть "рейсов". Я также внесли некоторые изменения в мою конфигурацию rewrite, в которой последнее добавило следующее правило, чтобы игнорировать этот путь для углового приложения и обрабатывать их напрямую: <add input="{REQUEST_URI}" matchType="Pattern" pattern="(.*)_escaped_fragment_=(.*)" ignoreCase="false"/>

Я отделяю свой код от тех, кто приходит и говорит, что он укорачивает вашу проблему, поскольку это может быть...

  • первая часть, мои конфиги и небольшие коды
  • второй учебник, который я прочитал о PhantomeJS
  • другие файлы, которые могут потребоваться

Вот моя основная настройка:

WebConfig Перепишите:

<rewrite>
  <rules>
    <!--<rule name="Seo rewrite rule" stopProcessing="true">
      <conditions>
        <add input="{QUERY_STRING}" pattern="(.*)_escaped_fragment_=(.*)" ignoreCase="false" />
      </conditions>
      <action type="Rewrite" url="http://service.prerender.io/http://{HTTP_HOST}{REQUEST_URI}" appendQueryString="false" />
    </rule>-->
    <rule name="Index Rule" stopProcessing="true">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/api/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Token" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/bundles/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Content/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Scripts/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/SiteMap/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/CallBackBank/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Error/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="(.*)_escaped_fragment_=(.*)" ignoreCase="false" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/HtmlSnapshot[^s]?/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Flight[^s]?/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Hotel[^s]?/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Tour[^s]?/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/TravelAgency[^s]?/" negate="true" />
        <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Users[^s]?/" negate="true" />
      </conditions>
      <action type="Rewrite" url="/" />
    </rule>
  </rules>
</rewrite>

Phantom JS требуется Фильтр:

public class AjaxCrawlableAttribute : System.Web.Mvc.ActionFilterAttribute
{
    private const string Fragment = "_escaped_fragment_";
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var request = filterContext.RequestContext.HttpContext.Request;
        var url = request.Url.ToString();
        if (request.QueryString[Fragment] != null && !url.Contains("HtmlSnapshot/returnHTML"))
        {
            url = url.Replace("?_escaped_fragment_=", string.Empty).Replace(request.Url.Scheme + "://", string.Empty);
            url = url.Split(':')[1];
            filterContext.Result = new RedirectToRouteResult(
               new RouteValueDictionary { { "controller", "HtmlSnapshot" }, { "action", "returnHTML" }, { "url", url } });
        }
        return;
    }
}

Конфигурация маршрута:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.LowercaseUrls = true;

        //PhantomJS
        routes.MapRoute(
            name: "HtmlSnapshot",
            url: "HtmlSnapshot/returnHTML/{*url}",
            defaults: new {controller = "HtmlSnapshot", action = "returnHTML", url = UrlParameter.Optional});
        ////PhantomJS
        //routes.MapRoute(
        //    name: "SPA",
        //    url: "{*catchall}",
        //    defaults: new {controller = "Home", action = "Index"});

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

PhantomJS для С# Учебник, который я читаю: ОК, так как учебник, который я читал о phantomjs, находится в неанглийском языке, я публикую то, что написал для моего более позднего использования:

1.Установить пакет

Install-Package PhantomJS.exe -version 1.9.2.1

2. Помогите Помощнику

public class AjaxCrawlableAttribute : System.Web.Mvc.ActionFilterAttribute
{
    private const string Fragment = "_escaped_fragment_";
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var request = filterContext.RequestContext.HttpContext.Request;
        var url = request.Url.ToString();
        if (request.QueryString[Fragment] != null && !url.Contains("HtmlSnapshot/returnHTML"))
        {
            url = url.Replace("?_escaped_fragment_=", string.Empty).Replace(request.Url.Scheme + "://", string.Empty);
            url = url.Split(':')[1];
            filterContext.Result = new RedirectToRouteResult(
               new RouteValueDictionary { { "controller", "HtmlSnapshot" }, { "action", "returnHTML" }, { "url", url } });
        }
        return;
    }
}

3.Replace Default Routes With:

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "HtmlSnapshot",
            url: "HtmlSnapshot/returnHTML/{*url}",
            defaults: new { controller = "HtmlSnapshot", action = "returnHTML", url = UrlParameter.Optional });

        //If doesn't work, use default route instead...:
        routes.MapRoute(
        name: "SPA",
        url: "{*catchall}",
        defaults: new { controller = "Home", action = "Index" });
    }

4.Add AjaxCrawlableAttribute как фильтр

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new AjaxCrawlableAttribute());
    }
}

5.Создать контроллер HtmlSnapshot

public ActionResult returnHTML(string url)
    {
        var prefix = HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Host + ":";
            url = prefix + url;
            string appRoot = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
            var startInfo = new ProcessStartInfo
            {
                Arguments = string.Format("{0} {1}", "\"" + Path.Combine(appRoot, "Scripts\\seo.js") + "\"", url),
                FileName = "\"" + Path.Combine(appRoot, "bin\\phantomjs.exe") + "\"",
            UseShellExecute = false,
            CreateNoWindow = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            RedirectStandardInput = true,
            StandardOutputEncoding = System.Text.Encoding.UTF8
        };
        var p = new Process();
        p.StartInfo = startInfo;
        p.Start();
        string output1 = p.StandardOutput.ReadToEnd();
        p.WaitForExit();
        var removeNgUiView = output1.Replace("<!-- ngView:  -->", "").Replace("ng-view=\"\"", "");
        removeNgUiView = Regex.Replace(removeNgUiView, "<!--\\suiView:\\s\\w*\\s-->", "");
        removeNgUiView = Regex.Replace(removeNgUiView, "(<\\w+[^>]*)(ui-view(=\"\\w*\")?)([^<]*>)", "$1$4");
        removeNgUiView = Regex.Replace(removeNgUiView, "(<\\w+[^>]*)(ng-app(=\"\\w*\")?)([^<]*>)", "$1$4");
        ViewData["result"] = removeNgUiView;
        return View();
    }

6.Создание представлений контроллера

@{
    Layout = null;
}
@Html.Raw(ViewData["result"])

7.Создание seo.js в скрипте (! Важно) Папка

var page = require('webpage').create();
    var system = require('system');

    var lastReceived = new Date().getTime();
    var requestCount = 0;
    var responseCount = 0;
    var requestIds = [];
    var startTime = new Date().getTime();;
    page.onResourceReceived = function (response) {
        if (requestIds.indexOf(response.id) !== -1) {
            lastReceived = new Date().getTime();
            responseCount++;
            requestIds[requestIds.indexOf(response.id)] = null;
        }
    };
    page.onResourceRequested = function (request) {
        if (requestIds.indexOf(request.id) === -1) {
            requestIds.push(request.id);
            requestCount++;
        }
    };

    function checkLoaded() {
        return page.evaluate(function () {
            return document.all["compositionComplete"];
        }) != null;
    }
    // Open the page
    page.open(system.args[1], function () {

    });

    var checkComplete = function () {
        // We don't allow it to take longer than 5 seconds but
        // don't return until all requests are finished
        if ((new Date().getTime() - lastReceived > 300 && requestCount === responseCount) || new Date().getTime() - startTime > 10000 || checkLoaded()) {
            clearInterval(checkCompleteInterval);
            console.log(page.content);
            phantom.exit();
        }
    }
    // Let us check to see if the page is finished rendering
    var checkCompleteInterval = setInterval(checkComplete, 300);

8.Layout.cshtml Основано на:

<!DOCTYPE html>
<html ng-app="appOne">
<head>
    <meta name="fragment" content="!">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta charset="utf-8" />
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <meta name="viewport" content="width=device-width" />
    <base href="/">
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    <script src="~/Scripts/angular/angular.js"></script>
    <script src="~/Scripts/angular/angular-route.js"></script>
    <script src="~/Scripts/angular/angular-animate.js"></script>
    <script>
        angular.module('appOne', ['ngRoute'], function ($routeProvider, $locationProvider) {
            $routeProvider.when('/one', {
                template: "<div>one</div>", controller: function ($scope) {
                }
            })
            .when('/two', {
                template: "<div>two</div>", controller: function ($scope) {
                }
            }).when('/', {
                template: "<div>home</div>", controller: function ($scope) {
                }
            });
            $locationProvider.html5Mode({
                enabled: true
            });
        });
    </script>
</head>
<body>
    <div id="body">
        <section ng-view></section>
        @RenderBody()
    </div>
    <div id="footer">
        <ul class='xoxo blogroll'>
            <li><a href="one">one</a></li>
            <li><a href="two">two</a></li>
        </ul>
    </div>
</body>
</html>

ПРИМЕЧАНИЕ. PhantomJS не может обрабатывать персидские ссылки (UTF-8)

Третья часть, другие вещи, которые вам могут потребоваться, чтобы знать... Я не вижу никакой другой вещи, которая может быть задействована, если вы заметили, что спросите меня, я отредактирую свой вопрос.

  • 0
    Модератору, могу ли я добавить статью в раздел phantomjs по этому вопросу?
Теги:
asp.net-mvc
phantomjs
url-rewriting

2 ответа

0
Лучший ответ

Вот что я сделал:

для конфигурации:

<rule name="Crawler" stopProcessing="false">
  <match url=".*"/> <!-- rule back-reference is captured here -->
  <conditions logicalGrouping="MatchAll">
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="(.*)_escaped_fragment_=(.*)" ignoreCase="true" negate="true" /><!-- condition back-reference is captured here -->
  </conditions>
  <action type="Rewrite" url="{R:0}" /><!-- rewrite action uses back-references to condition and to rule when rewriting the url -->
</rule>
<rule name="Index Rule" stopProcessing="true">
  <match url=".*" />
  <conditions logicalGrouping="MatchAll">
    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/api/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Token" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/bundles/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Content/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Scripts/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/SiteMap/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/CallBackBank/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Error/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/HtmlSnapshot[^s]?/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Flight[^s]?/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Hotel[^s]?/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Tour[^s]?/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/TravelAgency[^s]?/" negate="true" />
    <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/Users[^s]?/" negate="true" />
  </conditions>
  <action type="Rewrite" url="/" />
</rule>

И вот для фильтра:

var request = filterContext.RequestContext.HttpContext.Request;
        if (request.Url == null)
            return;
var url = request.Url.Scheme + "://" + request.Url.Authority + request.RawUrl; //THIS LINE ('RowUrl' contains rest of the path)
0

Я написал небольшую статью об этом, просто некоторые простые настройки, он проверен и работает, посмотри на это

Добавьте в свою маршрутизацию:

$locationProvider.html5Mode(true); 

Страница индекса:

<base href="/">

И web.config:

<system.webServer>
    ...........
</system.webServer>

Вы сделали.

  • 0
    Переписывание само по себе работает хорошо, моя проблема в том, когда я смешиваю его с учебным кодом, о котором я говорил. затем, когда я использую URL-адрес ?_escaped_fragment_= (add ?_escaped_fragment_= ), он перемещается только на первую страницу углового приложения, что означает, что он может прочитать часть пути, или в этом конкретном случае он перенаправляется на почтовый URL-адрес, а затем передается phantomJS Handler (рукописный код AjaxCrawlableAttribute ).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню