SEO friendly URL using URL Routing in Asp.Net + C# - c#

I have a simple web form application. I have one page called "show.aspx" which is responsible for displaying my article by an article Id.
At first I used to use QueryString to fetch article Id and on the basis of that Id I displayed article. However I knew that the url was not SEO friendly.
My URL was like this: mysite.com/article/show.aspx?articleid=7737
So I decided to move to URL rewriting, but since I had no experience in that I ended up with using URL routing technique.
So currently my url is like this: mysite.com/article/7737/
It works fine. I get the value of article with {articleid} parameter, defined in my global.asax file.
But I want to get my url something like this:
mysite.com/article/article-title-from-database/
is it possible to fetch the title from database and re write url with applying hyphen between each word?
even I am ok if I need to pass two parameters like this:
article/{articleid}/{title}/
Following is my Global.asax
<%# Application Language="C#" %>
<%# Import Namespace="System.Web.Routing" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute("ArticleDetails","article/{articleId}", "~/article/show.aspx");
}
</script>
And My show.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (RouteData.Values["articleId"].ToString() != string.Empty)
{
Articles.rptArticle = rptDisplayArticle;
Articles.rptHashTags = rptHashTags;
Comments.rptComments = rptDisplayComments;
Articles.articleId = RouteData.Values["articleId"] as string;
Articles.Show();
if (!Comments.show())
{
lblNoComments.Text = "NO COMMENTS";
}
if (Authorization.Authorize())
{
panCommentPost.Visible = true;
ltLoginPrompt.Text = "POST A COMMENT";
}
}
else
{ Server.Transfer("~/404.html"); }

Related

Encode hash in ReturnUrl ASP.NET Login control

We have a ASP.NET login control in our aspx:
<asp:Login ID="LogOnControl" runat="server" OnLoginError="OnLogOnError" OnLoggedIn="OnLoggedIn">
and in OnLoggedIn we do:
protected void OnLoggedIn(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString["ReturnUrl"]))
{
Response.Redirect(Request.QueryString["ReturnUrl"]);
}
}
and our ReturnUrl should be something like Default.aspx#/Projects
The problem is that all after hash is trimmed. We need to pass entire URL to server (so encode it somehow).
Jabko87 - you cannot get values after # because it is not being sent to the server. You must develop your own mechanism to handle it.
Compare: Pass URL's with hash value for redirection
And: How to get Url Hash (#) from server side
I achieved it by defining hidden input on aspx page:
<input type="hidden" id='<%= ReturnUrlHash %>' name='<%= ReturnUrlHash %>' />
and filling it with JS:
document.getElementById('<%= ReturnUrlHash %>').value = window.location.hash;
and on server side in Logon.aspx.cs I did:
public const string ReturnUrlHash = "returnUrlHash";
protected void OnLoggedIn(object sender, EventArgs e)
{
string returnUrl = Request.QueryString["ReturnUrl"];
if (!string.IsNullOrEmpty(returnUrl))
{
if (Request.Form.AllKeys.Contains(ReturnUrlHash))
{
returnUrl += Request.Form[ReturnUrlHash];
}
Response.Redirect(returnUrl);
}
}

add dynamic data to an Existing Web Site but it does not work

I have added dynamic data to an Existing Web Site but it doesn't work .
this is the error that i see :
HTTP Error 404.0 - Not Found The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
this is my Global.asax :
<%# Application Language="C#" %>
<%# Import Namespace="System.ComponentModel.DataAnnotations" %>
<%# Import Namespace="System.Web.Routing" %>
<%# Import Namespace="System.Web.DynamicData" %>
<%# Import Namespace="System.Web.UI" %>
<script RunAt="server">
private static MetaModel s_defaultModel = new MetaModel();
public static MetaModel DefaultModel {
get {
return s_defaultModel;
}
}
public static void RegisterRoutes(RouteCollection routes) {
// IMPORTANT: DATA MODEL REGISTRATION
// Uncomment this line to register an ADO.NET Entity Framework model for ASP.NET Dynamic Data.
// Set ScaffoldAllTables = true only if you are sure that you want all tables in the
// data model to support a scaffold (i.e. templates) view. To control scaffolding for
// individual tables, create a partial class for the table and apply the
// [ScaffoldTable(true)] attribute to the partial class.
// Note: Make sure that you change "YourDataContextType" to the name of the data context
// class in your application.
// See http://go.microsoft.com/fwlink/?LinkId=257395 for more information on how to add and configure an Entity Data model to this project
DefaultModel.RegisterContext(typeof(BasijeDaneshgahMarvdashtModel.BasijeDaneshgahMarvdashtEntities), new ContextConfiguration() { ScaffoldAllTables = true });
// The following statement supports separate-page mode, where the List, Detail, Insert, and
// Update tasks are performed by using separate pages. To enable this mode, uncomment the following
// route definition, and comment out the route definitions in the combined-page mode section that follows.
routes.Add(new DynamicDataRoute("{table}/{action}.aspx") {
Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert" }),
Model = DefaultModel
});
// The following statements support combined-page mode, where the List, Detail, Insert, and
// Update tasks are performed by using the same page. To enable this mode, uncomment the
// following routes and comment out the route definition in the separate-page mode section above.
//routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx") {
// Action = PageAction.List,
// ViewName = "ListDetails",
// Model = DefaultModel
//});
//routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx") {
// Action = PageAction.Details,
// ViewName = "ListDetails",
// Model = DefaultModel
//});
}
private static void RegisterScripts() {
ScriptManager.ScriptResourceMapping.AddDefinition("jquery", new ScriptResourceDefinition
{
Path = "~/Scripts/jquery-1.7.1.min.js",
DebugPath = "~/Scripts/jquery-1.7.1.js",
CdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js",
CdnDebugPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.js",
CdnSupportsSecureConnection = true,
LoadSuccessExpression = "window.jQuery"
});
}
void Application_Start(object sender, EventArgs e) {
RegisterRoutes(RouteTable.Routes);
RegisterScripts();
}
</script>

Call Webmethod in Usercontrol.cs from Usercontrol.ascx javascript

I have a usercontrol and in that I have a javascript function which makes a call to webmethod.
<%# Control Language="C#" AutoEventWireup="true" CodeFile="LeftMenu.ascx.cs"
Inherits="UserControls_LeftMenu" %>
<script type="text/javascript">
function GetRealTimeCount() {
PageMethods.CountOfMenus('', '', GetCountOfMenus_Success, GetCountOfMenus_Fail);
}
My webmethod code is
[System.Web.Services.WebMethod]
public static string CountOfMenus(string StartDate, string EndDate)
{
//Code here
}
But when I run the code, it gives me javascript error, CountOfMenus is undefined. I know the error is because it cant find the method in the current page but I want it to access method in the usercontrol.cs. I cant write the webmethod in every page as I have lots of pages where the usercontrol is used. Is there any way through which I can call the method of usercontrol.cs in javascript?
I solved this by below method
Javascript :
function GetRealTimeCount(StartDate, EndDate) {
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
var url = "Default.aspx?Method=CountOfMenus&SD=" + StartDate + "&ED=" + EndDate;
xmlhttp.open("Get", url, false);
xmlhttp.send(null);
document.getElementById("Count").innerHTML = xmlhttp.responseText;
}
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["Method"] == "CountOfMenus")
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
GetCount(Request.QueryString["SD"], Request.QueryString["ED"]);
}
}
private void GetCount(string StartDate, string EndDate)
{
Response.Clear();
// Code to get count
Response.Write(Count.ToString());
Response.End();
}
The below link from where I got these solutions has many other options to call C# methods from javascript
http://www.morgantechspace.com/2014/01/Call-Server-Side-function-from-JavaScript-in-ASP-NET.html
when your JS code calls a PageMethod using "PageMethods." , the call does not reach the page method if it was defined in the control. The page methods in the page are only callable.
I suggest another approach, using Http Handler which is also efficient.
Try follow this post:
Call HttpHandler from javascript
Also, the following post might be useful:
http://www.undisciplinedbytes.com/2010/03/ajax-call-using-an-asp-net-http-handler/
Do you have ScriptManager in your UserControl Page?
if not you have to add it and set EnablePageMethods="true"
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
</asp:ScriptManager>

ASP.NET ReturnURL to specific search results page

I have an ASP.net site with C# backend code. We have the following (abridged) code in it, which suits our needs, but it could be better. This is on a page called SearchResults.aspx. If the user is not logged in, the links will redirect them to the login page. If they are logged in, it will redirect them to a lookup page for that item. What I want it to do is to redirect them to the corresponding item page after they log in if they click the "not logged in link". In what way would I need to supply the returnURL to the login page? Every way I've tried, it just redirects me to the default page after login.
<AnonymousTemplate>
<!--Want to change the link below so that the return URL will take me to
ItemInformation.aspx-->
<%# DataBinder.Eval(Container.DataItem, "itemnumber").ToString().Trim() %><br/>
<asp:HyperLink runat="server" ID="HyperLink1" NavigateUrl='Account/Login.aspx'>
Please login to review information for this item.</asp:HyperLink>
</AnonymousTemplate>
<LoggedInTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%#
"~/ItemInformation.aspx?&ItemID=" + DataBinder.Eval(Container.DataItem,
"itemnumber").ToString().Trim() + "&itemdept=" + DataBinder.Eval(
Container.DataItem, "department").ToString()%>'
Text='<%# DataBinder.Eval(Container.DataItem, "itemnumber")%>'>
</asp:HyperLink>
</LoggedInTemplate>
Edit - I'm using the default login structure for an ASP.net Web Application template, so this is all that is in the Login backend.
protected void Page_Load(object sender, EventArgs e)
{
string returnUrl = Request.QueryString["ReturnUrl"];
RegisterHyperLink.NavigateUrl = "Register.aspx?ReturnUrl=" +
HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]);
}
On SearchResults.aspx
if (!Request.IsAuthenticated)
{
Response.Redirect("/Login.aspx/?ReturnURL="+HttpContext.Current.Request.Url.AbsoluteUri); // dont forget to use urlencode
}
On Login.aspx
protected void Login_Click()
{
if (Request.QueryString["ReturnURL"] != null)
{
Response.Redirect(Request.QueryString["ReturnURL"]);
}
else
{
Response.Redirect("/Home.aspx");
}
}
In one of my attempts to try to get it to work, I was only attempting to set the DestinationPageUrl attribute for my asp:Login control. For some reason, it required me to use both this and the OnLoggedIn event together (I was not aware of this events existence before Zerkey pointed it out). The Additional question mark in the return URL was also causing issues, so here's what I did in Login.aspx.
Markup:
<asp:Login ID="LoginUser" runat=server" EnableViewState="false"
RenderOuterTable="false" OnLoggedIN="UserLoginOnLoggedIn">...</asp:Login>
Code:
protected void UserLoginOnLoggedIn(object sender, EventArgs e)
{
string itemid, itemdept;
try
{
s1 = Request.QueryString["ItemID"].Trim();
s2 = Request.QueryString["Dept"].Trim();
}
catch
{
//makes strings null if querystrings aren't present
s1 = "";
s2 = "";
}
string returnUrl = Request.QueryString["ReturnUrl"] + "&ItemID=" +
Request.QueryString["ItemID"] + "&Dept=" +
Request.QueryString["Dept"];
if ((!String.IsNullOrEmpty(returnUrl) && !String.IsNullOrEmpty(s1) &&
!String.IsNullOrEmpty(s2)))
LoginUser.DestinationPageUrl = returnUrl;
else
LoginUser.DestinationPageUrl = "~/Default.aspx";
Response.Redirect(LoginUser.DestinationPageUrl);
}

Simple log in with Facebook C# SDK not working

I'm new to the Facebook apps and recently read the doc available. Then, I proceeded to get the Facebook C# SDK from NuGet and read the get started tutorial.
I modified it a little. I have 3 pages:
Default.aspx : has the "log in with facebook" button
Protected.aspx : the page that I ultimately want to be unaccessible without first logging in
DoSignIn.aspx : contains the request for the token and redirects back to Default.aspx
On the Default.aspx, I have a button that redirects me to the Protected.aspx page. On it, I have a label showing me the token.
Now, my issue is this:
When I click on the "log in with facebook" button, the button doesn't change to show that I'm logged in. It only shows that I'm logged in if I do a refresh on the page.
If I click on the button to redirect me to the Protected.aspx page, I can't see the token in the Label because the DoSignIn.aspx page was never called.
If someone could point me in what I do wrong (as I nearly copied the tutorial example), I would be very grateful. I spent the past 3 hours fiddling with this and searching Google and SO all over and don't know where to search anymore.
Thank you for your time.
PS. I have the latest Facebook C# SDK and the App ID seems to work fine as when I manually refresh my browser, I am indeed logged in.
I add the code for the 3 pages:
Default.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<div id="fb-root">
</div>
<script type="text/javascript">
window.fbAsyncInit = function () {
FB.init({
appId: 'I_INSERTED_MY_APP_ID_HERE', // App ID
status: true, // check login status
cookie: true, // enable cookies to allow the server to access the session
xfbml: true // parse XFBML
});
FB.Event.subscribe('auth.authResponseChange', function (response) {
if (response.status === 'connected') {
// the user is logged in and has authenticated your
// app, and response.authResponse supplies
// the user's ID, a valid access token, a signed
// request, and the time the access token
// and signed request each expire
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
// - Handle the access token -
// Do a post to the server to finish the logon
// This is a form post since we don't want to use AJAX
var form = document.createElement("form");
form.setAttribute("method", 'post');
form.setAttribute("action", 'DoSignIn.aspx');
var field = document.createElement("input");
field.setAttribute("type", "hidden");
field.setAttribute("name", 'accessToken');
field.setAttribute("value", accessToken);
form.appendChild(field);
document.body.appendChild(form);
form.submit();
} else if (response.status === 'not_authorized') {
// the user is logged in to Facebook,
// but has not authenticated your app
} else {
// the user isn't logged in to Facebook.
}
});
};
// Load the SDK Asynchronously
(function (d) {
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) { return; }
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
} (document));
</script>
<form id="form1" runat="server">
<div>
<div class="fb-login-button" data-show-faces="true" data-width="400" data-max-rows="1">
Log in with Facebook</div>
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Go to protected" />
</div>
</form>
</body>
</html>
Default.aspx.cs:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Response.Redirect("Protected.aspx");
}
}
DoSignIn.aspx.cs:
public partial class DoSignIn : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var accessToken = Request["accessToken"];
Session["AccessToken"] = accessToken;
Response.Redirect("Default.aspx");
}
}
Protected.aspx.cs:
public partial class Protected : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Session["AccessToken"] != null)
{
Label1.Text = Session["AccessToken"].ToString();
}
else
{
Label1.Text = "Not authenticated";
}
}
Right, I have spent hours searching and finally found why it is not working. It has nothing to do with the code above but with a Facebook bug. Actually, it seems that many people can't have the auth.authResponseChange to fire as the session refreshes. I found several bugs reports on FB describing the complete issue, one of them being here.
This issue I had when developing on /localhost/. I had already moved to a different way to integrate Facebook Login when, before deleting the above samples, I tried uploading it on an actual hosting server under a domain name. For a reason I can't explain, it just works from there.
Anyway, the implementation for the Facebook login I'm currently pursuing is explained here.

Categories