learning mvc and building a full blown ecommerce app.
Administrators should be able to add-edit whatever they like.
Let's take an example Employees.
I have added an Area called "Admin".Within admin I have Employees
In here an administrator should be able to add-edit info about employees.
Now in the user section the user should not be able to add-edit.etc..
At them moment I have 2 controllers?
Areas-Admin-Controllers-EmployeeController
Areas-Aboutus-Controllers-EmployeeController
It does not seem right to me.How do you handle such a code repetition?
I would like to have only one controller.How do you structure your mvc app in this case?
any example I can download?
Looking for a good examples where you can see areas working and running themes dynamically etc..
thanks for any suggestions
You could use a single ~/Controllers/EmployeesController controller to handle the Employee resource in your application. Inside this controller actions that require administrative (or some logged in user) privileges could be decorated with the [Authorize] attribute by specifying the required roles in order to execute this action:
public class EmployeesController: Controller
{
// Anyone can list employees, even anonymous users
public ActionResult Index()
{
IEnumerable<Employee> employees = _repository.GetEmployees();
return View(employees);
}
public ActionResult Show(int employeeId)
{
Employee employee = _repository.GetEmployee(employeeId);
return View(employee);
}
// Only administrators can update employees
[Authorize(Roles = "admin")]
[HttpPost]
public ActionResult Update(Employee employee)
{
_repository.Update(employee);
return RedirectToAction("Index");
}
// Only administrators can delete employees
[HttpDelete]
[Authorize(Roles = "admin")]
public ActionResult Destroy(int employeeId)
{
_repository.Delete(employeeId);
return RedirectToAction("Index");
}
... and some other actions following the Simply RESTful pattern:
http://mvccontrib.codeplex.com/wikipage?title=SimplyRestfulRouting
}
I'm assumuing your doing it this way so that you can use authentication and have the pretty urls:
/Admin/Employee
/Aboutus/Employee
How about only having a single controller in /Controllers/EmployeeController. You can set [Authorize] attribute on any methods that you need authentication for and control the urls with custom routes?
routes.MapRoute( _
"Admin_Employee", _
"Admin/{controller}/{action}/{id}", _
New With {.controller = "Employee", .action = "Index", .id = UrlParameter.Optional} _
)
routes.MapRoute( _
"AboutUs_Employee", _
"Aboutus/{controller}/{action}/{id}", _
New With {.controller = "Employee", .action = "Details", .id = UrlParameter.Optional} _
)
Related
So I can make an address like
www.mysite.com/person
But how can I make it so that it's like
www.mysite.com/person/john-bishop
I guess I need both ID and name, in case there are multiple john bishops?
This is what I got so far
public ActionResult Person(int id, string name)
{
return View();
}
You need add an Id or unique identifier at the end.
www.mysite.com/person/john-bishop-1
www.mysite.com/person/john-bishop-2
and the RouteConfig
routes.MapRoute("Person", "Person/{name}-{id}", new { controller = "Person", action = "Person" });
I have 2 tables tbl_client and tbl_branch linked with the client_id. I have created a ClientController and a BranchController.
Now I need to control the branch under client view. I have and ActionLink
#Html.ActionLink("Branch Management", "Index", "Branch", new {id = item.client_id},null)
This will redirect to Index view in branch controller, where the list of branches according to client id is filtered and return the view.
Now I have a create link in this view and I need to redirect it to the Create Page which will Create the Branch Under the Client currently active.
just put the client_id in a viewbag from your Branch-> Index actionresult.
Public ActionResult Index(string id){
ViewBag.ClientId=id;
}
now goto its view; Index.cshtml and say,
#Html.ActionLink("New Client", "Create", "Client", new {id = ViewBag.ClientId});
Just Make a Link into View as:
#Html.ActionLink("Branch Create", "Create", "Branch", new {id = item.client_id})
and on Server side (i.e. In Controller) use action as:
//GET
public ActionResult Create(long Client_ID)
{
var NewBranch=new BranchViewModel{Client_ID=Client_ID};
return View(NewBranch);
}
//POST
[HttpPost]
public ActionResult Create(BranchViewModel Branch)
{
//Code to Create New Entry
}
Maybe this can help you.
I am developing an ASP.Net MVC Website which the expected routing behavior is like Facebook
When user is not logged in and access the site he is showed the welcome page under
www.domain.com/
If he logs in we want him to access the website content still in
www.domain.com/
How should i define the routes?
Edit: To clarify more as instructed
I want to serve a different Index action if a user is logged in and a different if he is not.
An approach that doesn't work
[Authorize]
public ActionResult Index()
{
return View();
}
[AllowAnonymous]
public ActionResult Index()
{
return View();
}
So with two different Index Actions the default Route
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }
will perform as i want.
By looking in the MSDN Documentation i found out i can pass the name of the View i want in the constructor.For the sake of completeness here is my implementation.
public ActionResult Index()
{
if (User.Identity.IsAuthenticated)
{
return View();
}
else
{
return View("Welcome");
}
}
I have the following actionresult:
public ActionResult Confirmation(string emailAddress)
When I try to access it:
http://localhost:8080/Signup/Confirmation?emailAddress=test%40test.com
I get this:
The view 'test#test.com' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Signup/test#test.com.cshtml
~/Views/Signup/test#test.com.vbhtml
What gives why isn't it looking for the correct view? If I go to "/SignUp/" it correctly shows me the index, along with the other ActionResults working correctly. Why does an address break it?
You shouldn't be passing that info in the URL anyway.
If this is kind of a "Confirmation" page from a signup, you could pass another identifier, e.g the UserId that has just been created, then fetch it from the repo.
E.g:
[HttpPost]
public ActionResult Signup(SignupViewModel model)
{
//.. code to save.. etc
return RedirectToAction("Confirmation", new { id = newUser.UserId });
}
[HttpGet]
public ActionResult Confirmation(int id)
{
var user = repo.FindById(id);
// map to model, etc...
return View(model);
}
So your URL would be (without a specialized route)
http://localhost:8080/Signup/Confirmation?id=123213
Putting user's email addresses in the URL is asking for them to be spammed.
Have you tried registering the route in the global.asax.cs?
Something like:
routes.Add("confirmation",
new Route("Signup/Confirmation/{email}",
new RouteValueDictionary(new { controller = "Signup", action = "Confirmation", email = UrlParameter.Optional }),
new MvcRouteHandler())
);
I must be dense. After asking several questions on StackOverflow, I am still at a loss when it comes to grasping the new routing engine provided with ASP.NET MVC. I think I've narrowed down the problem to a very simple one, which, if solved, would probably allow me to solve the rest of my routing issues. So here it is:
How would you register a route to support a Twitter-like URL for user profiles?
www.twitter.com/username
Assume the need to also support:
the default {controller}/{action}/{id} route.
URLs like:
www.twitter.com/login
www.twitter.com/register
Is this possible?
What about
routes.MapRoute(
"Profiles",
"{userName}",
new { controller = "Profiles", action = "ShowUser" }
);
and then, in ProfilesController, there would be a function
public ActionResult ShowUser(string userName)
{
...
In the function, if no user with the specified userName is found, you should redirect to the default {controller}/{action}/{id} (here, it would be just {controller}) route.
Urls like www.twitter.com/login should be registered before that one.
routes.MapRoute(
"Login",
"Login",
new { controller = "Security", action = "Login" }
);
The important thing to understand is that the routes are matched in the order they are registered. So you would need to register the most specific route first, and the most general last, or all requests matching the general route would never reach the more specific route.
For your problem i would register routing rules for each of the special pages, like "register" and "login" before the username rule.
You could handle that in the home controller, but the controller method would not be very elegant. I'm guessing something like this might work (not tested):
routes.MapRoute(
"Root",
"{controller}/{view}",
new { controller = "Home", action = "Index", view = "" }
);
Then in your HomeController:
public ActionResult Index(string view) {
switch (view) {
case "":
return View();
case "register":
return View("Register");
default:
// load user profile view
}
}
OK I haven't ever properly tried this, but have you tried to extend the RouteBase class for dealing with users. The docs for RouteBase suggest that the method GetRouteData should return null if it doesn't match the current request. You could use this to check that the request matches one of the usernames you have.
You can add a RouteBase subclass using:
routes.Add(new UserRouteBase());
When you register the routes.
Might be worth investigating.
i think your question is similar to mine. ASP.NET MVC Routing
this is what robert harvey answered.
routes.MapRoute( _
"SearchRoute", _
"{id}", _
New With {.controller = "User", .action = "Profile", .id = ""} _
)
Here is an alternative way to standar route registration:
1. Download RiaLibrary.Web.dll and reference it in your ASP.NET MVC website project
2. Decoreate controller methods with the [Url] Attributes:
public SiteController : Controller
{
[Url("")]
public ActionResult Home()
{
return View();
}
[Url("about")]
public ActionResult AboutUs()
{
return View();
}
[Url("store/{?category}")]
public ActionResult Products(string category = null)
{
return View();
}
}
BTW, '?' sign in '{?category}' parameter means that it's optional. You won't need to specify this explicitly in route defaults, which is equals to this:
routes.MapRoute("Store", "store/{category}",
new { controller = "Store", action = "Home", category = UrlParameter.Optional });
3. Update Global.asax.cs file
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoutes(); // This do the trick
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
How to set defaults and constraints? Example:
public SiteController : Controller
{
[Url("admin/articles/edit/{id}", Constraints = #"id=\d+")]
public ActionResult ArticlesEdit(int id)
{
return View();
}
[Url("articles/{category}/{date}_{title}", Constraints =
"date=(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])")]
public ActionResult Article(string category, DateTime date, string title)
{
return View();
}
}
How to set ordering? Example:
[Url("forums/{?category}", Order = 2)]
public ActionResult Threads(string category)
{
return View();
}
[Url("forums/new", Order = 1)]
public ActionResult NewThread()
{
return View();
}