I am working at an ASp.net mvc 3 project and
I keep getting this error and can find any help to solve the problem
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies)
could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /RoomType
But I have The RoomType controller and in my Global.asax I have:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
null, // we don't need to specify a name
"Page{page}",
new { Controller = "Room", action = "List" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Room", action = "List", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
null, // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Room", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
null, // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "RoomType", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Here is my RoomTypeController :
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication4.Models;
namespace MvcApplication4.Controllers
{
public class RoomTypeController : Controller
{
private hotelEntities db = new hotelEntities();
//
// GET: /RoomType/
public ViewResult Index(int start = 0, int itemsPerPage = 20, string orderBy = "RoomType_ID", bool desc = false)
{
ViewBag.Count = db.Room_Type.Count();
ViewBag.Start = start;
ViewBag.ItemsPerPage = itemsPerPage;
ViewBag.OrderBy = orderBy;
ViewBag.Desc = desc;
return View();
}
//
// GET: /RoomType/GridData/?start=0&itemsPerPage=20&orderBy=RoomType_ID&desc=true
public ActionResult GridData(int start = 0, int itemsPerPage = 20, string orderBy = "RoomType_ID", bool desc = false)
{
Response.AppendHeader("X-Total-Row-Count", db.Room_Type.Count().ToString());
ObjectQuery<Room_Type> room_type = (db as IObjectContextAdapter).ObjectContext.CreateObjectSet<Room_Type>();
room_type = room_type.OrderBy("it." + orderBy + (desc ? " desc" : ""));
return PartialView(room_type.Skip(start).Take(itemsPerPage));
}
//
// GET: /Default5/RowData/5
public ActionResult RowData(int id)
{
Room_Type room_type = db.Room_Type.Find(id);
return PartialView("GridData", new Room_Type[] { room_type });
}
//
// GET: /RoomType/Create
public ActionResult Create()
{
return PartialView("Edit");
}
//
// POST: /RoomType/Create
[HttpPost]
public ActionResult Create(Room_Type room_type)
{
if (ModelState.IsValid)
{
db.Room_Type.Add(room_type);
db.SaveChanges();
return PartialView("GridData", new Room_Type[] { room_type });
}
return PartialView("Edit", room_type);
}
//
// GET: /RoomType/Edit/5
public ActionResult Edit(int id)
{
Room_Type room_type = db.Room_Type.Find(id);
return PartialView(room_type);
}
//
// POST: /RoomType/Edit/5
[HttpPost]
public ActionResult Edit(Room_Type room_type)
{
if (ModelState.IsValid)
{
db.Entry(room_type).State = EntityState.Modified;
db.SaveChanges();
return PartialView("GridData", new Room_Type[] { room_type });
}
return PartialView(room_type);
}
//
// POST: /RoomType/Delete/5
[HttpPost]
public void Delete(int id)
{
Room_Type room_type = db.Room_Type.Find(id);
db.Room_Type.Remove(room_type);
db.SaveChanges();
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
Make sure that your controller class is called RoomTypeController (and not RoomType, and not RoomController) and that it contains an Index action:
public class RoomTypeController : Controller
{
public ActionResult Index()
{
return View();
}
}
Related
How to retrieve the ViewModel from within an exception filter?
I have an ExceptionFilter, which I am using for a global error handler in an asp .net core 3.1 MVC application. I am trying to get the exception filter to redirect back to the View when there is an error and show validation errors, ie the equivalent of saying:
return View(viewModel)
in the controller
I can redirect to the View, but am a little stuck on how to populate the Model in the ViewResult
ExceptionFilter code
public void OnException(ExceptionContext context)
{
string controller = context.RouteData.Values["controller"].ToString();
string action = context.RouteData.Values["action"].ToString();
if (context.Exception is WebServiceException && context.Exception.IsUnauthorized())
{
context.Result = new RedirectToActionResult("fetchtoken", "Home", new { path = $"/{controller}/{action}" });
}
//other type of exception, return the view displaying errors
else
{
context.ModelState.Clear();
context.ModelState.AddModelError(action, $"error in {action}");
m_Logger.LogError(context.Exception, $"error in {action}");
context.ExceptionHandled = true;
context.ModelState
context.Result = new ViewResult{
ViewName = action,
ViewData = // ??????????????
};
}
}
In the controller:
[Authorize]
[HttpPost]
public async Task<IActionResult> AuthoriseApiUser(AuthoriseApiViewModel viewModel)
{
await m_ApiUserService.AuthoriseUser(viewModel.TenantId, viewModel.UserId); //error thrown here
return View(viewModel);
}
Through obtaining the value of each key in the form data, the value is compared with the property of the model. Then, assign value to model. For example.
public void OnException(ExceptionContext context)
{
string controller = context.RouteData.Values["controller"].ToString();
string action = context.RouteData.Values["action"].ToString();
//start
var viewModel = new ViewModel();
var list = context.HttpContext.Request.Form.AsEnumerable();
foreach (var meta in list)
{
if (meta.Key == "addr")
{
viewModel.addr = meta.Value;
}
}
//end
if (context.Exception is WebServiceException && context.Exception.IsUnauthorized())
{
context.Result = new RedirectToActionResult("fetchtoken", "Home", new { path = $"/{controller}/{action}" });
}
//other type of exception, return the view displaying errors
else
{
//...
var modelMetadata = new EmptyModelMetadataProvider();
context.Result = new ViewResult
{
ViewName = action,
ViewData = ViewData = new ViewDataDictionary(modelMetadata, context.ModelState)
{
Model = viewModel
}
};
}
}
Model
public class ViewModel
{
public int id { get; set; }
[MinLength(2)]
public string addr { get; set; }
}
I would like to be able to create a succinct language-specific default URL for my website so that when someone browses to:
somesite.com
They get redirected to a language-culture page such as:
somesite.com/en-US/
somesite.com/sp-MX/
somesite.com/fr-FR/
Specifically, I do not want /Home/Index appended to the URLs:
somesite.com/en-US/Home/Index
somesite.com/sp-MX/Home/Index
somesite.com/fr-FR/Home/Index
I am committed to making this site using RouteLocalization.mvc
Dresel/RouteLocalization
Translating Your ASP.NET MVC Routes
And I would like to use MVC Attribute Routing to the extent feasible.
I am having trouble figuring out how to cause the Start() method redirect to a language-culture specific URL without the addition of something like "index".
Samples of what I have attempted follow:
using RouteLocalization.Mvc;
using RouteLocalization.Mvc.Extensions;
using RouteLocalization.Mvc.Setup;
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.Clear();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes(Localization.LocalizationDirectRouteProvider);
const string en = "en-us";
ISet<string> acceptedCultures = new HashSet<string>() { en, "de", "fr", "es", "it" };
routes.Localization(configuration =>
{
configuration.DefaultCulture = en;
configuration.AcceptedCultures = acceptedCultures;
configuration.AttributeRouteProcessing = AttributeRouteProcessing.AddAsNeutralAndDefaultCultureRoute;
configuration.AddCultureAsRoutePrefix = true;
configuration.AddTranslationToSimiliarUrls = true;
}).TranslateInitialAttributeRoutes().Translate(localization =>
{
localization.AddRoutesTranslation();
});
CultureSensitiveHttpModule.GetCultureFromHttpContextDelegate = Localization.DetectCultureFromBrowserUserLanguages(acceptedCultures, en);
var defaultCulture = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
routes.MapRoute(
name: "DefaultLocalized",
url: "{culture}/{controller}/{action}/{id}",
constraints: new { culture = #"(\w{2})|(\w{2}-\w{2})" },
defaults: new { culture = defaultCulture, controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
And my home controller:
public class HomeController : Controller
{
[HttpGet]
[Route]
public RedirectToRouteResult Start()
{
return RedirectToAction("Home", new { culture = Thread.CurrentThread.CurrentCulture.Name });
}
[Route("Index", Name = "Home.Index")]
public ActionResult Index()
{
return View();
}
public ActionResult Contact()
{
return View();
}
public ActionResult About()
{
return View();
}
}
My Global.asax file:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
AreaRegistration.RegisterAllAreas();
}
}
Redirecting is a separate concern than routing. Since your goal of redirecting any URL to its localized counterpart is a cross-cutting concern your best bet is to make a global filter.
public class RedirectToUserLanguageFilter : IActionFilter
{
private readonly string defaultCulture;
private readonly IEnumerable<string> supportedCultures;
public RedirectToUserLanguageFilter(string defaultCulture, IEnumerable<string> supportedCultures)
{
if (string.IsNullOrEmpty(defaultCulture))
throw new ArgumentNullException("defaultCulture");
if (supportedCultures == null || !supportedCultures.Any())
throw new ArgumentNullException("supportedCultures");
this.defaultCulture = defaultCulture;
this.supportedCultures = supportedCultures;
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var routeValues = filterContext.RequestContext.RouteData.Values;
// If there is no value for culture, redirect
if (routeValues != null && !routeValues.ContainsKey("culture"))
{
string culture = this.defaultCulture;
var userLanguages = filterContext.HttpContext.Request.UserLanguages;
if (userLanguages.Length > 0)
{
foreach (string language in userLanguages.SelectMany(x => x.Split(';')))
{
// Check whether language is supported before setting it.
if (supportedCultures.Contains(language))
{
culture = language;
break;
}
}
}
// Add the culture to the route values
routeValues.Add("culture", culture);
filterContext.Result = new RedirectToRouteResult(routeValues);
}
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// Do nothing
}
}
Usage
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new RedirectToUserLanguageFilter("en", new string[] { "en", "de", "fr", "es", "it" }));
filters.Add(new HandleErrorAttribute());
}
}
Note also that your routing is misconfigured. The route setup is run one time per application startup, so setting the default culture to that of the current thread is meaningless. In fact, you should not be setting a default culture at all for your culture route because you want it to miss so your Default route will execute if there is no culture set.
routes.MapRoute(
name: "DefaultLocalized",
url: "{culture}/{controller}/{action}/{id}",
constraints: new { culture = #"(\w{2})|(\w{2}-\w{2})" },
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I have created a sub-domain route class in RouteConfig.cs as:
public class SubdomainRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
if (httpContext.Request == null || httpContext.Request.Url == null)
{
return null;
}
var host = httpContext.Request.Url.Host;
var index = host.IndexOf(".");
string[] segments = httpContext.Request.Url.PathAndQuery.TrimStart('/').Split('/');
if (index < 0)
{
return null;
}
var subdomain = host.Substring(0, index);
string[] blacklist = { "www", "yourdomain", "mail","localhost" };
if (blacklist.Contains(subdomain))
{
return null;
}
string controller = (segments.Length > 0) ? segments[0] : "Home";
if (controller == "")
controller = "Home";
string action = (segments.Length > 1) ? segments[1] : "Index";
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values.Add("controller", controller);
routeData.Values.Add("action", action);
routeData.Values.Add("subdomain", subdomain);
return routeData;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
I updated RegisterRoutes function to :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new SubdomainRoute());
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{category}/{subcategory}/{lowcategory}/{id}",
defaults: new { controller = "Home", action = "Index",category=UrlParameter.Optional,subcategory=UrlParameter.Optional,lowcategory=UrlParameter.Optional, id = UrlParameter.Optional }
);
}
My Index function is :
public string Index(string category, string subcategory, string lowcategory,int? id)
Now the link http://localhost:29808/Home/Index/mobiles/Htc/M8/3 is working fine but with subdomain its not working electronics.localhost:29808/Home/Index/mobiles/HTC/M8/3. (It shows null in category and subcategory). What else if have to include to make it work?
Here's an example. Assuming you have the following action:
public AccountController : Controller
{
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Foo(string id)
{
return View();
}
}
And the following route registered:
RouteTable.Routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "home", action = "index", id = "" }
);
I test it like this:
var routeData = "~/account/foo".WithMethod(HttpVerbs.Post);
routeData.Values["id"] = "123";
routeData.ShouldMapTo<AccountController>(c => c.Foo("123"));
But this work too with Get, and don't have to work:
var routeData = "~/account/foo".WithMethod(HttpVerbs.Get);
routeData.Values["id"] = "123";
routeData.ShouldMapTo<AccountController>(c => c.Foo("123"));
Why?
UPDATE 1:
My Real methods are:
public ActionResult Novo()
{
NovoViewModel novoViewModel = new NovoViewModel();
novoViewModel.Sexos = GetSexos();
novoViewModel.Status = GetStatus();
return View(novoViewModel);
}
[HttpPost]
public ActionResult Novo(NovoViewModel novoViewModel)
{
//Validações de autenticação
if (_authenticationService.IsUserRegistered(novoViewModel.NomeUsuario))
{
ModelState.AddModelError("ExistingUsername", String.Format(ViewModelValidations.ExistingUsername, "Usuário"));
}
if (_usuarioRepository.PegaUsuarioPorEmail(novoViewModel.Email) != null)
{
ModelState.AddModelError("ExistingEmail", String.Format(ViewModelValidations.ExistingEmail, "Email"));
}
if (ModelState.IsValid) {
Usuario usuario = new Usuario()
{
Nome = novoViewModel.Nome,
Email = novoViewModel.Email,
Telefone = novoViewModel.Telefone,
DataNascimento = Convert.ToDateTime(novoViewModel.DataNascimento),
Sexo = !String.IsNullOrEmpty(novoViewModel.SexoSelecionado) ? (Sexo?)(Convert.ToByte(novoViewModel.SexoSelecionado)) : null,
Credencial = new Credencial()
{
NomeUsuario = novoViewModel.NomeUsuario,
Senha = novoViewModel.Senha,
Status = (Status)Convert.ToByte(novoViewModel.SexoSelecionado)
}
};
_usuarioRepository.Add(usuario);
_dbContext.SaveChanges();
return RedirectToAction("Index");
}
novoViewModel.Sexos = GetSexos();
novoViewModel.Status = GetStatus();
return View(novoViewModel);
}
Try putting id in url that you're testing:
var routeData = "~/account/foo/123".WithMethod(HttpVerbs.Post);
So this is the method in my repository I use to get records from my db via its Id
public BlogsTable GetBlogPosts(int id)
{
return db.BlogsTables.SingleOrDefault(d => d.Id == id);
}
And this is my controller using the get method
public ActionResult Details(int id)
{
BlogsTable blogPostDetails = repo.GetBlogPosts(id);
return View(blogPostDetails);
}
What I need is to be able to write a get method that allows me to get records from my db by the title, instead of its id. This is what I have now
Also, how to I set the route to use that method? This is what I have now
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Blog", action = "Index", id = "" }
);
public BlogsTable GetBlogPostsByTitle(string title)
{
return db.BlogsTables.SingleOrDefault(d => d.Title == title);
}
public ActionResult Details(string id)
{
BlogsTable blogPostDetails = repo.GetBlogPostsByTitle(id);
return View(blogPostDetails);
}