I Implement a web site with ASP.net MVC . it works fine in offline. but after uploading project on my Godaddy host, the URL changed.
My host in Godaddy is somehow that it supprts diffrent domains on one host. there is a website in my root and some folders for other websites. a structre is like below
I drag whole project to the folder test. suppose my domain is www.example.com and I Create a folder named test, and then attached the www.example.com to the \test folder. the problem is while I type www.exmple.com in the browser, then press enter, the URL change to 'www.example.com/test/en'( the 'en' is the name of my view) but the problem is that I do not want to have name of my folder(test) in the URL.
I am not sure if the problem is in my side or Godaddy , but here is my route config which it works exactly what I need in offline .
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
and here is my controller:
public class HomeController : Controller
{
public async Task<ActionResult> Index()
{
try
{
string userIpAddress = this.Request.UserHostAddress;
//string userIpAddress = "2.63.255.255";
var client = new HttpClient
{
BaseAddress = new Uri("http://freegeoip.net/xml/")
};
var response = await client.GetAsync(userIpAddress);
var content = await response.Content.ReadAsStringAsync();
var result = (Response)new XmlSerializer(typeof(Response)).Deserialize(new StringReader(content));
var country_name = result.CountryName;
var country_code = result.CountryCode;
TempData["Country_code"] = country_code;
TempData["Country_name"] = country_name;
if (country_code == "FR")
{
return RedirectToAction("en", "Home");
}
else if (country_code == "JP")
{
return RedirectToAction("en", "Home");
}
else if (country_code == "DE")
{
return RedirectToAction("en", "Home");
}
else
{
return RedirectToAction("en", "Home");
}
}
catch
{
return RedirectToAction("en", "Home");
}
}
public ActionResult en()
{
return View();
}
}
I want URL just change to www.example.com/en insted of www.example.com/test/en
Appreciate any help.
Related
I pull the tags in the news details section. The corresponding code block is below.
NewsDetail:
foreach (var item in etiketler.Take(1))
{
<span>#item</span>
}
foreach (var item in etiketler.Skip(1))
{
<span>#item</span>
}
Controller :
public ActionResult Tag(string tag, int? pageSize)
{
string id = this.RouteData.Values["tag"].ToString();
SectionServices _sectionServices = new SectionServices();
if (!pageSize.HasValue) pageSize = 1;
ViewBag.Current = pageSize;
Models.TagModel model = new Models.TagModel();
var dat = _sectionServices.getNewsByTag((int)pageSize, tag);
ViewData["etiket"] = tag;
if (dat != null)
{
ViewBag.Tag = tag;
model.getNews = dat;
return View(model);
}
return View();
}
Route Config :
routes.MapRoute(
name: "TagPage",
url: "{tag}-haberleri/{pageSize}",
defaults: new { controller = "Page", action = "Tag", pageSize = UrlParameter.Optional }
);
I get errors like "The controller for path '/Mert Hakan_haberleri / 2' was not found or does not implement IController" in log records. what is the cause of this error, clicking on tags works correctly, but I see this error in log records.
I also had this error. When I embedded the classes into a namespace, everything started working for me.
namespace PageControllers { // added this line!
public class PageController {
public ActionResult Tag() {
//code logic
return View();
}
}
}
How can I redirect Action which is not found in controller into another action within the same controller? Let's say that file abc.txt is requested via http://localhost:5000/Link/GetFile/abc.txt. My controller correctly serving that file. But now, i need to handle request such as http://localhost:5000/Link/Document/abc. Of course there is no any action matched to Document so I need to invoke function Error within the same controller (including id from original request).
I tried to solve this with StatusCodePagesWithReExecute function but then my File action is not working (each request goes directly to Error function).
I have following controller:
public class LinkController : ControllerBase
{
public IActionResult GetFile(string id)
{
return DownloadFile(id);
}
public IActionResult Error(string id)
{
return File("~/index.html", "text/html");
}
private FileResult DownloadFile(string fileName)
{
IFileProvider provider = new PhysicalFileProvider(#mypath);
IFileInfo fileInfo = provider.GetFileInfo(fileName);
var readStream = fileInfo.CreateReadStream();
return File(readStream, "text/plain");
}
}
and startup configuration:
app.UseDefaultFiles();
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "application/octet-stream",
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}"
);
});
Any clues how to solve this problem?
Regards
You can use UseStatusCodePages to achieve a simple redirection whenever there's a 404. Here's what it looks like:
app.UseStatusCodePages(ctx =>
{
if (ctx.HttpContext.Response.StatusCode == 404)
ctx.HttpContext.Response.Redirect("/Path/To/Your/Action");
return Task.CompletedTask;
});
Just add this somewhere above UseMvc.
EDIT:
I´m sorry, my first answer was not correct.
IRouteCollection router = RouteData.Routers.OfType<IRouteCollection>().First();
with this, you can match an url to controller action
Create HttpContext for testing (example with injection)
private readonly IHttpContextFactory _httpContextFactory;
public HomeController(
IHttpContextFactory httpContextFactory)
{
_httpContextFactory = httpContextFactory;
}
Create the context with values
HttpContext context = _httpContextFactory.Create(HttpContext.Features);
context.Request.Path = "/Home/Index";
context.Request.Method = "GET";
Check route
var routeContext = new RouteContext(context);
await router.RouteAsync(routeContext);
bool exists = routeContext.Handler != null;
Further reading: https://joonasw.net/view/find-out-if-url-matches-action
I've been searching and searching for away to make old URL like we used to do in aspx pages where you could have an alias pointing to a page like www.domain.com/my-great-alias point to www.domain.com/alias.aspx. I want to do the same thing in MVC but can not figure out how to make this happen in the route table. Where www.domain.com/my-great-alias would show up to the end user as such but point to www.domain.com/alias/2
Does this make sense to anyone else what I'm looking for?
// router
routes.MapRouteLowercase(
"Alias",
"{id}",
new
{
controller = "alias",
action = "select",
id = UrlParameter.Optional
}
);
// Alias controller
public ActionResult Select()
{
return View("select");
}
// Recipe Controller
public ActionResult Select()
{
return View();
}
You should be able to do this utilizing route config and parameters (as long as it's in the same domain):
Routing
routes.MapRoute(
name: "AliasRoute",
url: "{id}",
defaults: new { controller = "Alias" }
);
Controller
public class AliasController : Controller
{
public ActionResult Index(string id)
{
//DO SOME DATABASE STUFF HERE TO LOOKUP THE CORRESPONDIND CONTROLLER AND ACTION
var controllerAction = lookupControllerActionInDatabase(id);
return View(controllerAction.ViewName);
//OR
//DO CONDITIONAL CHECKS HERE AND RETURN THE APPROPRIATE VIEW
if (id == "my-great-alias") {
return View("Alias");
} else if (id == condition1) {
return View("viewForCondition1");
} else if (id == condition2) {
return View("viewForCondition2");
}
//AND SO ON...
}
}
All Im trying to do is get my url to have the blogid appending to it much like the following...
http://localhost/blog/blogpost/17
Here is my Controller...
public ActionResult BlogList(){ return View(_repository); }
public ActionResult BlogPost(string id)
{
ViewData["id"] = id;
if (ModelState.IsValid)
{
return RedirectToAction("BlogPost", new { id = id });
}
return View(_repository);
}
Now here is my route.config maproute
routes.MapRoute(
"MyBlog", // Route name
"blog/{action}/{id}", // URL with parameters
new { controller = "Blog", action = "blogpost", id =
UrlParameter.Optional } // Parameter defaults
);
Now I can get the url to appear when I click on a blog in the blogList. The page doesn't display the blog it displays a redirect loop message. If I omit the following code ...
if (ModelState.IsValid)
{
return RedirectToAction("BlogPost", new { id = id });
}
then I can display the blog. The url wont have the id value. Like this...
http://localhost/blog/blogpost/
What am I doing wrong?
The following code should work with your route:
// http://localhost/blog/bloglist
public ActionResult BlogList()
{
return View(_repository); // show all blog posts
}
// http://localhost/blog/blogpost/1
public ActionResult BlogPost(int? id = null)
{
if (id.HasValue == false || id.Value < 1)
{
// redirect to 404 page or BlogList
throw new NotImplementedException();
}
var blogPostObj = _repository.Find(id.Value);
if (blogPostObj == null)
{
// again redirect to 404
throw new NotImplementedException();
}
return View(blogPostObj);
}
Remove the BlogList() which takes 0 parameter
public ActionResult BlogList(){ return View(_repository); }
This is not required, since your id is type of string which can be null
The below code can be help you
public ActionResult BlogPost(string id)
{
var model=new ModelObject();
if(id!=null)
{
var model=Blogs.Find(id); //find it from repo
return View(model);
}
return View(model);
}
From your code it does not look like the id field is optional. Therefore I would change the route.
routes.MapRoute(
"MyBlog", // Route name
"blog/blogpost/{id}", // URL with parameters
new { controller = "Blog", action = "blogpost" },
new { id = #"(\d)+"} //ensures value is numeric.
);
RouteData.Values["id"] + Request.Url.Query
How does SO perform the URL rewrite if we only put in the question ID?
questions/{id}/{whatever}
to
questions/{id}/{question-slug}
I've been working for some time with MVC and I have it working (routes, action, everything) so that it picks up the right content based on the provided ID.
However, the part after the {id} (the slug part) stays the same as typed in. So if someone typed in content/5/foobar it will display the right content but will leave the foobar in there.
In the controller (or somewhere else, please suggest where) I would need to go into the DB and pull out the right slug, put it in the route data and then perform a redirect to the same action with this correct data, I guess?
This is a try with Execute Result override. It works but does not redirect or replace/display the correct URL in browser:
protected override void Execute(System.Web.Routing.RequestContext requestContext) {
if (requestContext.RouteData.Values["id"] != null) {
string currentSlug = _repository.Find(int.Parse(requestContext.RouteData.Values["id"].ToString())).Slug;
if (requestContext.RouteData.Values["slug"] != null) {
requestContext.RouteData.Values.Remove("slug");
}
requestContext.RouteData.Values.Add("slug", currentSlug);
}
base.Execute(requestContext);
}
This is another, nicely working, version of a Display action, so you can see what it does and get an idea what I want:
//
// GET: {culture}/directory/5/{slug}
public virtual ActionResult Display(int id, string slug)
{
var model = _repository.Find(id);
if (model != null) {
if (!model.Slug.Equals(slug, System.StringComparison.OrdinalIgnoreCase)) {
return RedirectToActionPermanent(pndng.DirectoryEntry.ActionNames.Display, pndng.DirectoryEntry.Name, new { id = model.Id, slug = model.Slug });
}
return View(model);
}
// no model found
return InvokeHttp404(HttpContext);
}
This one performs permanent redirect (it does what I want) but is it right?
I guess I need a redirect to refresh the browser URL, don't I?
public ActionResult Details(int id, string slug)
{
var session = MvcApplication.CurrentRavenSession;
var blogPostRelations = session
.Query<BlogPost, BlogPosts_WithRelatedData>()
.Where(x => x.IntId == id)
.As<BlogPostRelations>()
.FirstOrDefault()
;
if (blogPostRelations == null)
return HttpNotFound();
if (blogPostRelations.BlogPost.DisplayData.Slug.Value != slug)
return RedirectToActionPermanent("Details", new { id = id, slug = blogPostRelations.BlogPost.DisplayData.Slug.Value });
return View(blogPostRelations);
}
Notice the:
if (blogPostRelations.BlogPost.DisplayData.Slug.Value != slug)
return RedirectToActionPermanent("Details", new { id = id, slug = blogPostRelations.BlogPost.DisplayData.Slug.Value });
So your #2 approach is the right one.
You could write a custom route for this:
public class QuestionsRoute : Route
{
public QuestionsRoute()
: base(
"questions/{id}/{slug}",
new RouteValueDictionary(new
{
controller = "questions",
action = "index",
slug = UrlParameter.Optional
}),
new RouteValueDictionary(new
{
id = #"\d+"
}),
new MvcRouteHandler()
)
{ }
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var rd = base.GetRouteData(httpContext);
if (rd == null)
{
return null;
}
var id = rd.GetRequiredString("id");
var slug = rd.Values["slug"] as string;
if (string.IsNullOrEmpty(slug))
{
slug = GoFetchSlugFromDb(id);
if (string.IsNullOrEmpty(slug))
{
return null;
}
httpContext.Response.RedirectToRoutePermanent(new
{
action = "index",
controller = "questions",
id = id,
slug = slug
});
return null;
}
return rd;
}
private string GoFetchSlugFromDb(string id)
{
// TODO: you know what to do here
throw new NotImplementedException();
}
}
which will be registered in Application_Start:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add("questions", new QuestionsRoute());
}
Now your QuestionsController will be pretty simple:
public class QuestionsController: Controller
{
public ActionResult Index(int id, string slug)
{
...
}
}