I have the following url structure:
www.mysite.com/temporary/articles.php/artid=1
I would like to change it with:
www.mysite.com/temporary/articles/article-title-here.
where article-title should be based on artid .
Anyone can tell me how can I do that?
No .htaccess needed. I would create another controller method and add some routes. I would use the following approach:
You submit the following URL: www.mysite.com/temporary/articles.php/artid=1
CI catches it and reroutes it as such:
In your routes.php:
$route['temporary/articles.php/artid=(:any)'] = "temporary/articles/search_by_id/$1";
In your Controller:
class Articles extends CI_Controller {
public function index($title){
//load your model
//from your model, query your database to get your article info by title
//send results to your view.
}
public function search_by_id($id){
//load your model
//from your model, query your database to get your article title by id. Set it = $title
redirect("temporary/articles/$title")
}
}
Related
We currently have the following code on our custom DNN module:
public class FeatureController : ModuleSearchBase
{
public CommonDataDefinitions.Products.WebProductDetails ProductDetails { get; set; } = null;
public override IList<SearchDocument> GetModifiedSearchDocuments(ModuleInfo moduleInfo, DateTime beginDateUtc)
{
var searchDocuments = new List<SearchDocument>
{
WHAT CAN I RETURN HERE?
};
return searchDocuments;
throw new NotImplementedException();
}
}
Our Detailed Product View module retrieves the following information depending on the SKU in a query string on load using a web API Controller.
Product.Title
Product.Description
Product.Image
Product.Price
Product.DetailedDescription
Product.StockCode Product.MetaTitle
Product.MetaKeywords
Product.MetaDescription
The SearchModulebase code will be in the FeatureController class.
This page will be loaded each time someone looks at a product in detail when they navigate from the Product Filter Module.
1. Since the module will be loaded each time when someone clicks on a particular product. How do you run this code only once and return all the products from the API Controller? Do we need to create an Object which will retrieve everything?
2. How do you prevent the module from becoming slow when all the products have to be retrieved on the on load event?
3. Which SearchDocument information can be returned for the DNN Crawler to index?
4. When the DNN Crawler reads the Feature Controller code, how do you initialize your API Controller to go and fetch and Populate the results to be indexed?
I am porting a Asp.Net MVC application to Razor Pages.
In some of the controllers of the MVC application it makes use of return View("someOtherView", someModelForOtherView);
How do I port this to Razor Pages?
What I need to do is to transfer the request over to another Razor Page and pass the prepared PageModel to it (the other page does not need to execute OnMethod() but simply render its html.
Or, in other words, I only need to swap the template file that should be rendered with another one.
I cannot use Redirect as there must not be another roundtrip via the browser.
I doubt this is (easily) possible. From the github request that Lerner linked above, it's noted Razor Pages weren't designed to do that.
The closest workaround I was able to achieve was to turn my destination Razor Page into a View. (Hence, no code-behind.) Obviously that will only be possible if your destination page is never directly accessed via URL. For example, if you want to redirect to /Pages/MyPage, and you still need to be able to access the url http://example.com/MyPage, this won't work.
But, say all you want is a generic error or status page. Those don't have to be directly-accessible through URL. This works well for that.
Here's a couple extension methods on PageModel to do it, one that accepts models and one that doesn't:
public static ViewResult View(this PageModel pageModel, string viewName) {
return new ViewResult() {
ViewName = viewName,
ViewData = pageModel.ViewData,
TempData = pageModel.TempData
};
}
public static ViewResult View<TModel>(this PageModel pageModel, string viewName, TModel model) {
var viewDataDictionary = new ViewDataDictionary<TModel>(new EmptyModelMetadataProvider(), new ModelStateDictionary()) {
Model = model
};
foreach (var kvp in pageModel.ViewData) viewDataDictionary.Add(kvp);
return new ViewResult {
ViewName = viewName,
ViewData = viewDataDictionary,
TempData = pageModel.TempData
};
}
FYI, the reason for having to recreate the view dictionary is because the one in your pageModel is going to have a model type specific to the current Page, not to the View you're directing to, and you can't change the Model within a ViewDataDictionary to a different type. MVC would complain and throw an exception.
Usage:
public IActionResult OnGet(string id) {
// check if id is good here
if (idIsNoGood) return this.View("InvalidId", new ErrorModel...);
else {
return Page();
}
}
The above will look for InvalidId.cshtml view, which can be in the same folder as your page, the root /Pages/ folder, or /Pages/Shared/. And it'll still use your Layout too, like any other page.
Just make sure your cshtml file doesn't have a #page directive at the top; this won't work for a Razor page, only a View.
Example InvalidId.cshtml:
#model MyProject.Models.ErrorModel
<h1>Invalid Request</h1>
<p>#Model.Message</p>
Hi there
I'm working on a system where I have been asked to change the URL in the address line.
To take the short version, we have a profile page for all our lorries, let's say we have a lorry named SuperTransport, so I've made a routing that allows us to access his profile page by typing http: //app.fragtopgaver.dk/SuperTransport, problems are now that when you come to his profile page, something else says in the URL, which says http://app.fragtopgaver.dk/getindex/?slug=supertransport
I need that it still says http://app.fragtopgaver.dk/SuperTransport in the URL when landing on the page.
My routing looks like this:
routes.MapRoute(
name: "slug",
url: "{slug}",
defaults: new { controller = "Home", action = "show" },
constraints: new { slug = ".+" });
And in my Home Controller
public async Task<ActionResult> Show(string slug)
{
return RedirectToRoute(ProfileControllerRoute.GetIndex, new { slug = slug});
}
and my Profile Controller
[Route("GetIndex", Name = ProfileControllerRoute.GetIndex)]
public ActionResult Index(int? page, string slug = null)
Hope someone can give me a hint of what i can do about this.
The Answer was really simple, just had to add
[Route("{slug}")]
to the controller
Looking at Str::slug for my frontend URL generation but just wondering how you guys go about implementing it with routes etc, for example, how would you guys go about changing http://www.example.com/courses/1 to http://www.example.com/courses/this-course
OK, I did it this way:
// I have a slug field in my courses table and a slug field in my categories table, along with a category_id field in my courses table.
// Route
Route::get('courses/{categorySlug}/{slug?}', function($categorySlug, $slug) {
$course = Course::leftJoin('categories', 'categories.id', 'courses.category_id')
->where('categories.slug', $categorySlug)
->where('courses.slug', $slug)
->firstOrFail();
return View::make('courses.show')->with('course', $course);
});
Works like a charm. It gets the $categorySlug and $slug variables then uses them to filter the Eloquent model Course to get the correct course object from the database.
EDIT: You can generate a URL in your view like:
http://www.example.com/courses/it-training/mcse
By doing something like:
{{ $course->title }}
A have a method in my Category like below that retrieves the parent category slug. This could be better achieved though using some sort of presenter class which would allow you to simply use $course->url but I haven't got around to doing this yet. I will update the answer when I do.
public function parentCategorySlug($parentId)
{
if ($parentId === '0')
{
return $this->slug;
}
return $this->where('id', $parentId)->first()->slug;
}
You can use the cvierbrock's Eloquent-Sluggable package.
As for me I created a helper function and used the following method taken from here.
public static function getSlug($title, $model) {
$slug = Str::slug($title);
$slugCount = count( $model->whereRaw("url REGEXP '^{$slug}(-[0-9]*)?$'")->get() );
return ($slugCount > 0) ? "{$slug}-{$slugCount}" : $slug;
}
You can create a related model Slug, and approach the course in your methods like so:
$course = Slug::where('slug', $slug) -> firstOrFail() -> course;
I have also implemented a similar URL mapping but I preferred to have both the ID and the slug in the requested URL, like this:
http://www.example.com/courses/1/my-laravel-course
This method allows me to get the requested course object from the ID given in the URL, rather than having to store the slugs in my DB table.
Route::post('courses/(:num)/(:any)', function ($courseid, $slug) {
$course = Course::where('id', '=', $courseid)->get();
return View::make('courses.show')->with('course', $course);
}
For Laravel 8:
Given my URL:
http://www.example.com/courses/this-course
My route:
Route::get('/courses/{course:slug}' , function(Course $course){
return view('showCourse' , [
'course' => $course
])
})
I am trying to make a custom route but I cannot get it working and even though everything seems okay it always returns 404.
So here are the route defined.
It is defined first before the default and according to route debugger this is the route that gets hit.(Matched Route: Game/{id}/{title})
routes.Add(
"GamesDefault",
new Route("Game/{id}/{title}",
new RouteValueDictionary(new { controller = "Games", action = "ShowGame" }),
new DefaultMvcRouteHandler(urlTranslator, urlFoundAction)));
Here is the path Im trying to reach: /Game/5/test
And this is the Controller declaration. The GamesController is placed in the Controllers folder and its view are in Views/Games/showGames.cshtml.
public GamesController()
{
}
public ActionResult ShowGames(int id, string title)
{
return View(title);
}
The DefaultMvcRouteHandler doesnt do anything fancy.
public class DefaultMvcRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MvcHandler(requestContext);
}
}
The default route works without problems, and I have tried everything I can find like changing the name of the route so it doesnt match any folders or anything like that.
If anyone have any ideas on what more to try I would be most grateful.
As per my comment you are passing incorrect default route values for the controller and action values.
Update your route like so:
routes.Add(
"GamesDefault",
new Route("Game/{id}/{title}",
new RouteValueDictionary(new { controller = "GamesController", action = "ShowGames" }),
new DefaultMvcRouteHandler(urlTranslator, urlFoundAction)));