Добавление фиктивного домена в конец является своего рода исправлением и его следует избегать. Чтобы включить регистрацию имени пользователя, просто выполните следующие простые шаги.
Зарегистрироваться
Во время регистрации введите идентификатор пользователя, адрес электронной почты и пароль. Зарегистрируйте пользователя с обычной электронной почтой и паролем. При успешном его сохранении 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();
}
});
}
Bump!
MVC 5 Теперь поддерживает создание только строчных URL-адресов и общей политики конечной косой черты.
public static void RegisterRoutes(RouteCollection routes)
{
routes.LowercaseUrls = true;
routes.AppendTrailingSlash = false;
}
Также в моем заявлении, чтобы избежать дублирования контента на разных доменах / IP-адресах / корпусах писем и т. Д.
Я склонен создавать канонические 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-адрес запроса не соответствует ему.
Помимо публикации здесь, я отправил Скотту письмо по электронной почте, чтобы узнать, получился ли у него хороший ответ. Он привел пример добавления ограничений к маршрутам, чтобы вы могли реагировать только на строчные 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 для соответствия.
Я тоже работал над этим. Я, очевидно, буду откладывать Скотту на этом. Однако я смиренно предлагаю свое решение этой проблемы.
Добавьте следующий код в 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();
}
}
Отличный вопрос!
Я считаю, что есть лучший ответ на это. Если вы поместите каноническую ссылку в заголовок своей страницы, например:
<link rel="canonical" href="http://mydomain.com/Home/Index"/>
Тогда Google покажет только каноническую страницу в своих результатах, и что еще более важно, все гугл-блага будут переходить на эту страницу без штрафа.
Как и вы, У меня был тот же вопрос ; за исключением того, что я не желал соглашаться на ограничение 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).
Я действительно не знаю, как вы будете себя чувствовать через 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();
}
Основано на ответе Гейба Самнера, но без перенаправлений для 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.