Change URL After Action is Hit MVC? - c#

I want to change:
www.testurl.com/sports/blog/1
Where sports is my area, blog is my action and 1 is an ID of a blog post, to:
www.testurl.com/sports/blog/test-title-of-blog
Where blog is still my action but the id is not shown, but instead the title/permalink of the blog is.
Here is my AreaRegistration for this action:
context.MapRoute(
"sports",
"sports/{action}/{content}",
new { area = "Sports", controller = "Sports", action = "", content = "" });
Here is my action at the moment:
[HttpGet]
public ActionResult Blog(string content)
{
int contentId;
if (Int32.TryParse(content, out contentId))
{
model = service.GetBlogById(contentId);
}
else
{
model = service.GetBlogByTitle(content);
}
//Change URL to be: www.testurl.com/sports/blog/ + model.SEOFriendlyTitle
return View(model);
}
Users are able to search via the ID of the blog, but also by the title of it, but I only want the title to appear in the url bar, never the id.
I cannot do this via Redirect rules due to the continuing maintenance that would cause.
Is the controller the right place to do this? -Remember I may not have my title until after I retrieve it from the database using the ID
How would I go about changing the URL to display the title vs. the ID?

I think what you should do is return a RedirectResult to the new Url if the ID is numeric and is a valid contentId :
int contentId;
if (Int32.TryParse(content, out contentId))
{
model = service.GetBlogById(contentId);
if(model != null)
{
return RedirectResult(/*url using the title*/);
}
}
else
{
model = service.GetBlogByTitle(content);
}
//Change URL to be: www.testurl.com/sports/blog/ + model.SEOFriendlyTitle
return View(model);
Of course, that will cause another round trip to the server but I can see a way to change the browser URL without a page redirect. You should also make sure that all published urls on your site are using the title instead of Id.
I hope it will help.

I suggest giving this a quick read.
http://www.dominicpettifer.co.uk/Blog/34/asp-net-mvc-and-clean-seo-friendly-urls
If you are really can't have the ID in Url and don't want to do redirects then I think storing Url as Slugs in the database is the only other option.
*Some points if you are going to do this.*
Add a Unique Constraint to the column at the Database Level to avoid duplicates.
Create a Database Index on this column to speed up you reads.
So with this Url
www.testurl.com/sports/blog/test-title-of-blog
This is your unique slug that you will query the database for instead of an ID
test-title-of-blog

Related

How to access a UserID when a hyperlink is selected

Here is the hyperlinked code I am generating to show a list of merchants:
<td>
#Html.ActionLink(Html.DisplayFor(modelItem => item.MerchantName).ToHtmlString(), "ViewMerchant", "Merchants")
</td>
What I would like for it to do is to take me to a new page where it shows just the information on the merchant selected (address, webaddress, etc), so a ViewMerchant page in my Merchants View folder.
Can I grab the MerchantID in this ActionLink? If so how would that code look in the above ActionLink?
Secondly in the View Merchants page if anyone could link me to a site that would explain how to build that so the page gets populated with the merchant info would be ideal.
You can pass the MerchantID as a route value as follows:
#Html.ActionLink("Link text", "ViewMerchant", "Merchants", new { id = item.MerchantID }, null )
Where ViewMerchant is the name of your action instide MerchantsController
And here is a small sample to your details action:
public ActionResult Details(int id)
{
Merchant merchant = db.Merchants.Find(id);
return View(merchant);
}
Of course, you should use ViewModels instead of passing your model to the view. But that's another matter on which you can find many information online. Here is one link to start reading about it.

Redirect to more specific URL via routing

I am using the following routing in my project
routes.MapRoute(
"ProductRoute", // Route name
"product/{id}/{title}", // URL with parameters
new { controller = "product", action = "Index", id = UrlParameter.Optional }, // Parameters defaults
new[] { "PriceCompare.Controllers" }
);
The problem at hand is how the url is displayed in return. One can access the URL in any of the following ways:
http://mywebsite.com/product/22/full-title
http://mywebsite.com/product/22/half
http://mywebsite.com/product/22/
All is fine, as all these URLs redirect to the desired place. But, what i think would be nice is even if someone uses the 2nd or 3rd approach, the return URL in browser should show the 1st URI.
Just like StackOverflow. For example if you visit the following URL
stackoverflow.com/questions/734249/, your browser address will show the complete URL in browser stackoverflow.com/questions/734249/asp-net-mvc-url-routing-with-multiple-route-values
How can this be achieved?
You can either implement your own Route or do something like this in your action:
public ActionResult Index(int? id, string title = null)
{
if (String.IsNullOrWhiteSpace(title))
{
var product = // load product
return Redirect(Url.Action("Index", "Product",
new { id = id, title = product.Title }));
}
// your code
}

Insert data in SQL Server database from excel using HTTP Post

I want to insert data into SQL Server database when I click "Insert" button in excel.
The data is in Cells A2 and B2 and here is the code behind the "Insert" button in excel:
Dim HttpReq As New WinHttp.WinHttpRequest
HttpReq.Open "POST", "http://localhost:11121/Student/Insert/", False
HttpReq.Send "jsmith112"
Here is my code for the Controller action in VS:
[HttpPost]
public ActionResult Insert(string id)
{
try
{
student.AddToStudents(id);
student.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
This doesn't seem to be working, could anyone guide me into finishing this?
Thanks in advance
Just change the POST to
"http://localhost:11121/Student/Insert/" + id
and then map the route
routes.MapRoute(
"InsertStudent",
"Student/Insert/{id}",
new { controller = "Student", action = "Insert", id = "" }
);
and then in your controller you can check if id is empty, if not then make a new user
also, sometimes I do things like this
routes.MapRoute(
"Resource",
"{resource}/{operation}/{id}",
new { controller = "Resource", action = "Index", resource = "", operation = "" id = "" }
);
and then you could parse out what the things are..
as a side note and if you were making more end points for your service, you might consider using GET, POST, PUT, DELETE instead of actually having "Insert" in the URI. REST.
I don't think your controller action would see the data in this case. It has no way of knowing that the 'jsmith112' you sent should correspond to the string id parameter. Inside of your controller action, use the Request.InputStream object to grab the posted data and send that into the database.
A better way to do this would be to either send it through as url-encoded form data (so the post body would be 'id=jsmith112'), or to change the request to a GET (or a PUT, if you want to be properly RESTful) and hit this URL:
http://localhost:11121/Student/Insert/jsmith112
In that case it should be picked up by the string id parameter.
Also, put a breakpoint inside the controller action to be sure you're actually hitting it, then use the debugger to verify your web service has the data it needs.

ASP.NET MVC2 Custom routing with wildcard or free text url

I have a requirement to add specific functionality to an asp.net mvc2 web site to provide addtional SEO capability, as follows:
The incoming URL is plain text, perhaps a containing a sentence as follows
"http://somesite.com/welcome-to-our-web-site" or
"http://somesite.com/cool things/check-out-this-awesome-video"
In the MVC pipeline, I would like to take this URL, strip off the website name, look up the remaining portion in a database table and call an appropriate controller/view based on the content of the data in the table. All controllers will simply take a single parameter bieng the unique id from the lookup table. A different controller may be used depnding on different urls, but this must be derieved from the database.
If the url cannot be resolved a 404 error needs to be provided, if the url is found but obsolete then a 302 redirect needs to be provided.
Where the url is resolved it must be retained in the browser address bar.
I have had a look at the routing model, and custom routing and can't quite work out how to do it using these, as the controller would not be predefined, based on a simple route. I am also unsure of what to do to provide 404, 302 back to the headers also. Perhpas I need a custom httpmodule or similar but going there went beyond my understanding.
This must be possible somehow... we did it years ago in Classic ASP. Can anyone help with some details on how to achieve this?
Well, the simplest way would be to have an id somewhere in the url (usually the first option)
routes.MapRoute(
"SEORoute", // Route name
"{id}/{*seostuff}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional, seostuff = UrlParameter.Optional } // Parameter defaults
);
In your controller you'd have something like
public class HomeController {
public ActionResult Index(int id) {
//check database for id
if(id_exists) {
return new RedirectResult("whereever you want to redirect", true);
} else {
return new HttpNotFoundResult();
}
}
}
If you don't want to use the id method you could do something else like...
routes.MapRoute(
"SEORoute", // Route name
"{category}/{page_name}", // URL with parameters
new { controller = "Home", action = "Index", category = UrlParameter.Optional, pagename = UrlParameter.Optional } // Parameter defaults
);
public ActionResult Index(string category, string page_name) {
//same as before but instead of looking for id look for pagename
}
The problem with the latter is that you would need to account for all types of routes and it can get really difficult if you have a lot of parameters that match various types.
This should get you in the right direction. If you neeed some clarification let me know and I'll see if I can write a specific route to help you
Additional
You could probably do what you're looking for like
public ActionResult Index() {
//Create and instance of the new controlle ryou want to handle this request
SomeController controller = new SomeController();
controller.ControllerContext = this.ControllerContext;
return controller.YourControllerAction();
}
but I don't know any of the side effects by doing that...so it's probably not a good idea - but it seems to work.

ASP.NET MVC multiple url's pointing to the same action

How do i map multiple url's to the same action in asp.net mvc
I have:
string url1 = "Help/Me";
string url2 = "Help/Me/Now";
string url3 = "Help/Polemus";
string url1 = "Help/Polemus/Tomorow";
In my global.asax.cs file i want to map all those url to the following action:
public class PageController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
}
Now in MVC 5 this can be achieved by using Route Attribute.
[Route("Help/Me")]
[Route("Help/Me/Now")]
[Route("Help/Polemus")]
[Route("Help/Polemus/Tomorow")]
public ActionResult Index()
{
return View();
}
Add the following line to your routing table:
routes.MapRoute("RouteName", "Help/{Thing}/{OtherThing}", new { controller = "Page" });
EDIT:
foreach(string url in urls)
routes.MapRoute("RouteName-" + url, url, new { controller = "Page", action = "Index" });
In my case I was looking to simply combine two 'hardcoded' routes into one and stumbled upon this post. I wanted to clean out my RouteConfig.cs a little - because it had so many similar routes.
I ended up using some simple 'or' logic in a regular expression and basically changed:
routes.MapRoute(
"UniqueHomePage",
"Default",
new { controller = "Redirector", action = "RedirectToRoot" }
);
routes.MapRoute(
"UniqueHomePage2",
"Home",
new { controller = "Redirector", action = "RedirectToRoot" }
);
Into a single route:
routes.MapRoute(
"UniqueHomePageGeneric",
"{url}",
new { controller = "Redirector", action = "RedirectToRoot" },
new { url = "Home|Default" }
);
Note for the SEO-savy or -interested: The reason for pointing multiple URL's to one and the same action, is to then redirect them to one and the same page again. In this case the homepage. So the idea is to prevent duplicate content issues. When you use this method for pointing for NON redirecting actions, but actions that show their own views, then you might be CAUSING duplicate content issues :P.
You can just add the routes into your route table as you need them, same as any other route. Just give them unique names, hard coded URL and point them to the same controller / action. It will work fine.
If you use pattern matching instead of hard coded URLs just make sure you get all your routes in the right order so the correct one is selected from the list. So /Help/Me should appear before /Help/{Page} if the hard coded route goes to a different page to the pattern matched one. If you put /help/{page} in the route tabel 1st this will match to /help/me and your hard coded named action for that route would never fire.
On a side note, if this is a public facing site and SEO is important please be careful if you have multiple URLs returning the same data, it will be flagged as duplicate. If this is the case, then use the Canonical tag, this gives all the page rank from all the URLS that go to that single page to the one you name and removes the duplicate content issue for you.

Categories