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);
Related
I'm trying to build two routes only to action and to controller with id, keeping the default.
I have to access:
www.mysite.com/MyController/MyAction/{OptionalId}
www.mysite.com/MyController/{OptionalId}
www.mysite.com/MyActionFromHomeController
I was able to create routes to work with first and the third point, but not for the second. Current code:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "OnlyActionToHomeController",
url: "{action}",
defaults: new { controller = "Home" },
constraints: new { noConflictingControllerExists = new NoConflictingControllerExists() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
public class NoConflictingControllerExists : IRouteConstraint
{
private static readonly Dictionary<string, bool> _cache = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var path = httpContext.Request.Path;
if (path == "/" || String.IsNullOrEmpty(path))
return false;
if (_cache.ContainsKey(path))
return _cache[path];
IController ctrl;
try
{
var ctrlFactory = ControllerBuilder.Current.GetControllerFactory();
ctrl = ctrlFactory.CreateController(httpContext.Request.RequestContext, values["action"] as string);
}
catch
{
_cache.Add(path, true);
return true;
}
var res = ctrl == null;
_cache.Add(path, res);
return res;
}
}
I did!
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "OnlyController",
url: "{controller}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { id = #"\d+" } // define the id parameter needs to be integer
);
routes.MapRoute(
name: "OnlyActionToHomeController",
url: "{action}",
defaults: new { controller = "Home" },
constraints: new { noConflictingControllerExists = new NoConflictingControllerExists() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
public class NoConflictingControllerExists : IRouteConstraint
{
private static readonly Dictionary<string, bool> _cache = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var path = httpContext.Request.Path;
if (path == "/" || String.IsNullOrEmpty(path))
return false;
if (_cache.ContainsKey(path))
return _cache[path];
IController ctrl;
try
{
var ctrlFactory = ControllerBuilder.Current.GetControllerFactory();
ctrl = ctrlFactory.CreateController(httpContext.Request.RequestContext, values["action"] as string);
}
catch
{
_cache.Add(path, true);
return true;
}
var res = ctrl == null;
_cache.Add(path, res);
return res;
}
}
Below is the code
[Route("users/{userid}/create")]
public ActionResult CreateSellerProfile(string userId)
{
var country = _locationService.GetCountries().ToDictionary(x => x.Id, x => x.CountryName);
var model = new SellerProfileViewModel { CountryDic = country };
model.UserId = userId;
return View(model);
}
[Authorize]
[HttpPost]
[Route("users/create")]
public ActionResult CreateSellerProfile(SellerProfileViewModel model)
{
if (!ModelState.IsValid)
{
model.StateDic = _locationService.Getstates(model.CountryId).ToDictionary(x => x.Id, x => x.StateName);
model.CountryDic = _locationService.GetCountries().ToDictionary(x => x.Id, x => x.CountryName);
return View(model);
}
var checkForalreadyExists = _userService.GetSellerProfileByUserId(model.UserId);
if (checkForalreadyExists == null)
{
var domainSellerObj = Mapper.Map<SellerProfileViewModel, SellerProfile>(model);
_userService.SaveSellerProfile(domainSellerObj);
return RedirectToAction("CreateSellerProfile", new { model.UserId });
}
else
{
SetMessage(MessageType.Danger, MessageConstant.GetMessage(Messages.SellerProfileAdded));
return RedirectToAction("CreateSellerProfile", new { model.UserId });
}
}
I want to ask that after we do POST to this action CreateSellerProfile,
then we want to redirect again to the same action CreateSellerProfile empty page,
we are facing the problem that it's not able to find the route that we defined i.e [Route("users/{userid}/create")]
http://pastebin.com/WU7XS3Vs
You need to specify the parameter name (userId) in the anonymous object:
return RedirectToAction("CreateSellerProfile", new { userId = model.UserId });
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?
I am struck at this code, i get this error when whenever i tried to see a list of articles.
the error is The parameters dictionary contains a null entry for parameter articleId of non-nullable type System.Int32 for method System.Web.Mvc.ActionResult Detail(Int32) in Crossroads.Controllers.ArticleController. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters.
Here is the controller:
using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Security;
using Crossroads.Models;
using System.Linq;
using System.Web;
using Crossroads.Models.Repositories;
namespace Crossroads.Controllers
{
[HandleError]
public class ArticleController : BaseController
{
private IArticleRepository _ArticleRepository;
public ArticleController()
: this(new ArticleRepository())
{ }
public ArticleController(IArticleRepository articleRepo)
{
_ArticleRepository = articleRepo;
}
public ActionResult Index(bool? archived)
{
if (archived != null && archived.Value.Equals(true))
{
return View("IndexArchived", _ArticleRepository.ListArchivedArticles());
}
else
{
return View(_ArticleRepository.ListArticles());
}
}
public ActionResult Detail(int Id)
{
var article = _ArticleRepository.GetArticle(Id);
if (article.Published)
{
return View("Details", article);
}
else
{
postStatus = new PostStatusViewModel()
{
Status = Status.Warning,
Message = "I'm sorry, article " + article.Title + " has been deleted. <br />Please update your bookmark."
};
return RedirectToAction("PostStatus", postStatus);
}
}
public ActionResult Details(int id, string articleTitle)
{
return RedirectToAction("Detail", id);
}
[Authorize(Roles = "Manager")]
public ActionResult New()
{
return View("New", new Articles());
}
[Authorize(Roles = "Manager")]
[ValidateInput(false)]
public ActionResult Edit(int id)
{
var viewModel = _ArticleRepository.GetArticle(id);
return View(_ArticleRepository.GetArticle(id));
}
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
[Authorize(Roles = "Manager")]
public ActionResult Create(Articles model)
{
try
{
model.CreatedBy = Membership.GetUser().UserName;
model.CreatedDate = DateTime.Now;
model.ModifiedBy = Membership.GetUser().UserName;
model.ModifiedDate = DateTime.Now;
_ArticleRepository.CreateArticle(model);
return RedirectToAction("Index");
}
catch
{
return View("Edit", model.Id);
}
}
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
[Authorize(Roles = "Manager")]
public ActionResult Update(Articles model)
{
try
{
model.ModifiedBy = Membership.GetUser().UserName;
model.ModifiedDate = DateTime.Now;
_ArticleRepository.EditArticle(model);
return RedirectToAction("Details", new { id = model.Id });
}
catch (Exception ex)
{
_DBLogging.LoggError(ex);
postStatus = new PostStatusViewModel()
{
Status = Status.Error,
Message = ""
};
return View("Edit");
}
}
public JsonResult ManageArchiveArticle(int articleId, bool isArchived)
{
var result = new Dictionary<string, string>();
try
{
var article = _ArticleRepository.GetArticle(articleId);
article.IsArchived = isArchived ? false : true;
article.ModifiedBy = Membership.GetUser().UserName;
article.ModifiedDate = DateTime.Now;
if (article.IsArchived) article.ArchiveDate = DateTime.Now;
article = _ArticleRepository.EditArticle(article);
result.Add("isArchived", article.IsArchived.ToString().ToLower());
}
catch (Exception ex)
{
_DBLogging.LoggError(ex);
}
return Json(result);
}
public JsonResult ManagePublishArticle(int articleId, bool isPublished)
{
var result = new Dictionary<string, string>();
try
{
var article = _ArticleRepository.GetArticle(articleId);
article.Published = isPublished ? false : true;
article.ModifiedBy = Membership.GetUser().UserName;
article.ModifiedDate = DateTime.Now;
article = _ArticleRepository.EditArticle(article);
result.Add("isPublished", article.Published.ToString().ToLower());
}
catch (Exception ex)
{
_DBLogging.LoggError(ex);
}
return Json(result);
}
}
}
here is my index
<ul class="menu">
<li><%= Html.ActionLink("Article List", "Index", "Article")%></li>
<li><%= Html.ActionLink("New Article", "New", "Article")%></li>
</ul>
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();
}
}