Как я могу избежать дублирующегося содержания в ASP.NET MVC из-за нечувствительных к регистру URL и значений по умолчанию?

Добавление фиктивного домена в конец является своего рода исправлением и его следует избегать. Чтобы включить регистрацию имени пользователя, просто выполните следующие простые шаги.

Зарегистрироваться

Во время регистрации введите идентификатор пользователя, адрес электронной почты и пароль. Зарегистрируйте пользователя с обычной электронной почтой и паролем. При успешном его сохранении e-mail против user_id в отдельном узле (ветке).

mButtonSignUp.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(isValid()){
                mProgressBar.setVisibility(View.VISIBLE);
                final String userId = mEditTextUserId.getText().toString();
                final String emailId = mEditTextEmail.getText().toString() ;
                String password = mEditTextPassword.getText().toString() ;
                firebaseRef.createUser(emailId, password, new Firebase.ResultHandler() {
                    @Override
                    public void onSuccess() {
                       firebaseRef.child("user_ids").child(userId).setValue(emailId);
                       Toast.makeText(getBaseContext(),"You are successfully registered ",Toast.LENGTH_SHORT).show();
                       mProgressBar.setVisibility(View.GONE);
                    }

                    @Override
                    public void onError(FirebaseError firebaseError) {
                        mProgressBar.setVisibility(View.GONE);
                        Toast.makeText(getBaseContext(),firebaseError.toString(),Toast.LENGTH_SHORT).show();
                    }
                });

            }
        }
    });

База данных

Структура базы данных будет выглядеть так

Вход

Проверьте, введен ли пользователь в адрес электронной почты или пользователя. Если это идентификатор электронной почты, то непосредственно выполнить вход с ним, в противном случае получить идентификатор электронной почты, связанный с именем пользователя, и выполнить вход в систему.

    Button buttonLogIn = (Button)findViewById(R.id.button_login);
    buttonLogIn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {             

            mProgressBar.setVisibility(View.VISIBLE);
            String username = mEditTextEmail.getText().toString() ;
            final String password = mEditTextPassWord.getText().toString() ;

          //  Check if it is an email or not
             if(android.util.Patterns.EMAIL_ADDRESS.matcher(username).matches())                 {
                performLogin(username,password);
            }else{
              //get the emailId associated with the username      
        firebaseRef.child("user_ids").child(username)
              .addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if(dataSnapshot!=null){
                            String userId = dataSnapshot.getValue(String.class);
                            performLogin(userId,password);
                        }
                    }

                    @Override
                    public void onCancelled(FirebaseError firebaseError) {

                    }
                });
            }

        }
    });

private void performLogin(String emailId, String password) {
    firebaseRef.authWithPassword(emailId,password, new Firebase.AuthResultHandler() {
        @Override
        public void onAuthenticated(AuthData authData) {
            uid = authData.getUid() ;
            Toast.makeText(getBaseContext(), authData.toString(), Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onAuthenticationError(FirebaseError firebaseError) {
            Toast.makeText(getBaseContext(), firebaseError.toString(), Toast.LENGTH_SHORT).show();
        }
    });
}

23
задан Danny Tuppeny 19 June 2011 в 20:07
поделиться

7 ответов

Bump!

MVC 5 Теперь поддерживает создание только строчных URL-адресов и общей политики конечной косой черты.

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.LowercaseUrls = true;
        routes.AppendTrailingSlash = false;
     }

Также в моем заявлении, чтобы избежать дублирования контента на разных доменах / IP-адресах / корпусах писем и т. Д.

http://yourdomain.com/ru

https://yourClientIdAt.YourHostingPacket.com/

Я склонен создавать канонические URL-адреса на основе PrimaryDomain - Протокол - Контроллер - Язык - Действие

public static String GetCanonicalUrl(RouteData route,String host,string protocol)
{
    //These rely on the convention that all your links will be lowercase! 
    string actionName = route.Values["action"].ToString().ToLower();
    string controllerName = route.Values["controller"].ToString().ToLower();
    //If your app is multilanguage and your route contains a language parameter then lowercase it also to prevent EN/en/ etc....
    //string language = route.Values["language"].ToString().ToLower();
    return String.Format("{0}://{1}/{2}/{3}/{4}", protocol, host, language, controllerName, actionName);
}

Тогда вы можете использовать @Gabe Sumner's ] ответ, чтобы перенаправить на канонический URL вашего действия, если текущий URL-адрес запроса не соответствует ему.

3
ответ дан Anestis Kivranoglou 29 November 2019 в 02:46
поделиться

Помимо публикации здесь, я отправил Скотту письмо по электронной почте, чтобы узнать, получился ли у него хороший ответ. Он привел пример добавления ограничений к маршрутам, чтобы вы могли реагировать только на строчные URL:

public class LowercaseConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route,
            string parameterName, RouteValueDictionary values,
            RouteDirection routeDirection)
    {
        string value = (string)values[parameterName];

        return Equals(value, value.ToLower());
    }

И в методе регистрации маршрутов:

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

    routes.MapRoute(
        "Default",                                              // Route name
        "{controller}/{action}/{id}",                           // URL with parameters
        new { controller = "home", action = "index", id = "" },
        new { controller = new LowercaseConstraint(), action = new LowercaseConstraint() }
    );
}

Это начало, но Я хотел бы иметь возможность изменить генерацию ссылок из методов, таких как Html.ActionLink и RedirectToAction для соответствия.

9
ответ дан Drew Noakes 29 November 2019 в 02:46
поделиться

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

Добавьте следующий код в global.asax :

protected void Application_BeginRequest(Object sender, EventArgs e)
{
    // If upper case letters are found in the URL, redirect to lower case URL.
    if (Regex.IsMatch(HttpContext.Current.Request.Url.ToString(), @"[A-Z]") == true)
    {
        string LowercaseURL = HttpContext.Current.Request.Url.ToString().ToLower();

        Response.Clear();
        Response.Status = "301 Moved Permanently";
        Response.AddHeader("Location",LowercaseURL);
        Response.End();
    }
}

Отличный вопрос!

11
ответ дан Gabe Sumner 29 November 2019 в 02:46
поделиться

Я считаю, что есть лучший ответ на это. Если вы поместите каноническую ссылку в заголовок своей страницы, например:

<link rel="canonical" href="http://mydomain.com/Home/Index"/>

Тогда Google покажет только каноническую страницу в своих результатах, и что еще более важно, все гугл-блага будут переходить на эту страницу без штрафа.

2
ответ дан Timbo 29 November 2019 в 02:46
поделиться

Как и вы, У меня был тот же вопрос ; за исключением того, что я не желал соглашаться на ограничение URL-адреса в нижнем регистре, и мне тоже не понравился подход canonical (ну, это хорошо, но не само по себе).

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

Использовать его достаточно просто: каждый метод GET в классах контроллера должен добавить только одну строку в начале:

Seo.SeoRedirect(this);

Класс перезаписи SEO автоматически использует атрибуты Caller Info в C # 5.0 для сделайте тяжелую работу, сделав приведенный выше код строго копируя и вставляя.

Как я уже упоминал в связанной SO Q & amp; A, я работаю над тем, как преобразовать это в атрибут, но сейчас он выполняет свою работу.

Код форсирует один случай для URL. Регистр будет таким же, как и имя метода контроллера - вы выбираете, хотите ли вы использовать все заглавные буквы, все нижние или их комбинацию (CamelCase подходит для URL-адресов). Он выдаст 301 перенаправлений для совпадений без учета регистра и кэширует результаты в памяти для лучшей производительности. Он также перенаправляет завершающие обратные слэши (принудительно применяется для списков индексов, принудительно отключается в противном случае) и удаляет дублированный контент, доступ к которому осуществляется через имя метода по умолчанию (Index в стандартном приложении ASP.NET MVC).

1
ответ дан Community 29 November 2019 в 02:46
поделиться

Я действительно не знаю, как вы будете себя чувствовать через 8 лет, но теперь ASP MVC 5 поддерживает маршрутизацию атрибутов для удобного запоминания маршрутов и решения проблем с дублированным контентом для сайтов, дружественных к SEO

, просто добавьте маршруты .MapMvcAttributeRoutes (); в вашем RouteConfig, а затем определите один-единственный маршрут для каждого действия, например

    [Route("~/")]
    public ActionResult Index(int? page)
    {
        var query = from p in db.Posts orderby p.post_date descending select p;
        var pageNumber = page ?? 1;
        ViewData["Posts"] = query.ToPagedList(pageNumber, 7);         
        return View();
    }
    [Route("about")]
    public ActionResult About()
    {
        return View();
    }
    [Route("contact")]
    public ActionResult Contact()
    {
        return View();
    }
    [Route("team")]
    public ActionResult Team()
    {
        return View();
    }
    [Route("services")]
    public ActionResult Services()
    {
        return View();
    }
0
ответ дан Asad Ali 29 November 2019 в 02:46
поделиться

Основано на ответе Гейба Самнера, но без перенаправлений для JS, изображений и другого контента. Работает только на действиях контроллера. Идея состоит в том, чтобы сделать перенаправление позже в конвейере, когда мы уже знаем его маршрут. Для этого мы можем использовать ActionFilter.

public class RedirectFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var url = filterContext.HttpContext.Request.Url;
        var urlWithoutQuery = url.GetLeftPart(UriPartial.Path);
        if (Regex.IsMatch(urlWithoutQuery, @"[A-Z]"))
        {
            string lowercaseURL = urlWithoutQuery.ToString().ToLower() + url.Query;
            filterContext.Result = new RedirectResult(lowercaseURL, permanent: true);
        }

        base.OnActionExecuting(filterContext);
    }
}

Обратите внимание, что фильтр выше не перенаправляет и не изменяет регистр для строки запроса.

Затем привяжите ActionFilter глобально ко всем действиям, добавив его в GlobalFilterCollection.

filters.Add(new RedirectFilterAttribute());

Хорошая идея по-прежнему устанавливать для свойства LowercaseUrls значение true в RouteCollection.

0
ответ дан Edwin Stoteler 29 November 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: