I'm developing a sport based web site with Asp.Net Mvc 4.
The site is being developed to show just one sport data at a time.
The sports have similar datas in common but also they have different datas.
Site supports many sports that’s why, I do not want to use common controllers/views by seperating sports with if statements.
I tried this one:
I have created an area for each sport. I described the controllers in area which are related to that sport.
For example, in Route, name of the controller and area will be stated, firstly it will be searched in area, if it is not there, it will be searched in default(/Controllers).
Because the controllers share the same names, Mvc DefaultControllerfactory throws "Ambiguous Controller Name Exception". First I’m searching area, if it cannot be found then I’m searching in default by writing my own Controller factory. You can reach the project by the aid of the this link
In this case, my biggest deficiency is; without indicating namespace in route making the same thing in views. So it will search view in area, if it will not be found then it will search in default. Because the project is theme-supported, I use my own themable razor view engine, not default razor view engine. It can be reached by the aid of this link
base.AreaViewLocationFormats = new[]
{
_themeService.Current.BasePath + "/Views/Areas/{2}/{1}/{0}.cshtml",
_themeService.Current.BasePath + "/Views/{1}/{0}.cshtml",
_themeService.Current.BasePath + "/Views/Shared/{0}.cshtml","~/Themes/Default/Views/{1}/{0}.cshtml"
};
I updated the object of AreaViewLocationFormats of RazorViewEngine like this but regardless of the fact that I state area in route, it searches ViewLocationFormats instead of AreaViewLocationFormats if I do not state namespace.
In this case, how should I separate sports?
What I have done in a similar scenario is creating a base generic controller like this:
public abstract class BaseController<TModel> : Controller where TModel : class, new()
{
// Controller Actions to be shared by all the controllers that inherit form this one...
}
And, then your controllers will be like this:
public class TennisController : BaseController<Tennis>
{
}
Related
I'm using Telerik Kendo UI and apparently its grid view does not allow me to build it using a foreach loop and customize my table as it provides auto-binding. In this case it would not be possible for me to add action links to the table with particular route values.
In order to solve the problem, the easiest way that came into my mind (a fully non-js approach as I really don't enjoy Java Script) was to create two NotMapped read only properties in my Entity Model by extending the auto generated class by Entity Framework to:
[MetadataType(typeod(XModel))]
public partial class EntityX {
[NotMapped]
public String Edit => "<a href='ControllerName/ActionName?id="+ id.To.String()+"'>Edit</a>";
...
}
Although this approach is working, it has a very big problem and that is if I change the route config, then I have to update all the links!!
My question is that, how can I generate such Urls or action links similar to the way that #Html.ActionLink helper does in an area outside of both View and Controller (I mean I can't reuse the LinkExtensions) in order to solve the routing problem?
I have a project in which I need to check for and add a cookie, regardless of which view the user is currently on. I can place the code inside of the _Layout partial view within a code block, but I have doubts that's the conventional place for it. Where should it go?
View is generally wrong place to put logic.
Action filter is one possible way to centralize the code and allow easy customization, especially for something that sound so close to behavior of AuthorizeAttribute filter.
See Action Filtering in ASP.Net MVC for information.
public class MyCookieFilter : ActionFilterAttribute ...
[MyCookieFilter]
public ActionResult Index()
{
// The action method logic.
}
Side note: when searching for documentation be carefull to distinguish MVC and WebAPI classes - many have similar names and similar behavior, but can cause some confusion when applied to wrong objects.
I have 2 MVC projects. There is a common page that I want to reference directly instead of having to re-write. I'm doing so like this:
public ActionResult test()
{
OldController.Controllers.PatronController temp = new OldController.Controllers.PatronController();
return temp.Index();
}
The problem is, in "OldController" there is some functionality that get set in the OnActionExecuting function. When I call the function like I'm doing above, OnActionExecuting isn't being called.
How can I share the common page between the two projects (so I can return it OnActionExecuting?
Ideally, you want to keep navigation consistent in each project and still re-use the core functionality.
For that reason, I recommend:
1) creating a 3rd MVC Project with an Action Partial (Partial with Action Method -- and Controller).
2) Add a reference for your new MVC project to your 2 primary MVC projects.
3) In each of your primary MVC projects, create Views that render your Action Partial within a View.
Create a third project that is a class library and inside that library create a ControllerBase class that has the common functionality between the two controllers and in each project derive from that controller class.
I am doing big project in Web Forms and entered a big mess of code(can be solved with little refactoring), so I decided to take a peek at mvc, seems like everyone favores it over web forms.
I have dll file with all LINQ to SQL classes and methods for existing sql db and I started teaching myself by reacreating this project in mvc.I first recreated my homepage from webforms to razor, so far so good and I recreated one of the user controls to partial view and looped it.
Partial view is strongly typed with one of L2S class, the thing is there is some raw data in it.Like for example My model for partial view is my L2S class PostDetails: it consist od some data ready from output like: Title, Permalink, ViewsNumber etc. but it also cointains some raw data like UserId(I need to call method from dll to get username),DateTimeCreated(on which I also need to call method to get time difference), In webforms I would do this in codebehind but I'm not sure where to do it in mvc, maybe in controller and pass it in ViewData.I am also asking this for future, not just this case.
You should perform those actions in the controller. The controller is exactly what it sounds like, it controls the data flow between the model and the view.
Here is an example using your PostDetails:
PostDetailsModel
String Title {get;set;}
String Permalink {get;set;}
Int ViewNumber {get;set}
Int UserId {get;set}
DateTime DateTimeCreated {get;set;}
GetDetailsView: this will be requested by your user, and will be a visual representation of the PostDetailsModel (however you want to format that). When this View is requested, a call is made to your controller....
PostDetailsController
//This method will (by default) come from calling [BASEURL]/PostDetails/GetDetails
public ActionResult GetDetails()
{
var details = new PostDetailsModel();
details.UserId = GetUserId();
details.ViewNumber = GetViewNumber();
....
//By default this looks for a view in the PostDetails folder
//by the name of your method (GetDetails)
return View(details);
}
Notice how the controller is the router between the model and the view, basically. A note, however, it would be better to fill your model from methods contained within some sort of business layer (however you implement that). Something like var details = BL.GetDetails();
Also, when the user makes requests to save data, then you can do that with another method that takes the data (whether it be the PostDetailsModel or an int or...) and does whatever it needs to do, then it can redirect back to the display action (or wherever you need it to go)
There is a wealth of information on MVC with a simple google search. Here is Microsoft's overview, but the wikipedia article is very succinct if you just want the basics
In MVC, All your requests will be handled by an action method in a controller. and then controller returns a view. So you can get the data in your controller (or a different layer which will be called from the controller) and pass that data to your view.
Strongly typed views are a clean way of doing things. Create a ViewModel for your scenario. Mostly ViewModels looks similar to the Entities. Ex : For Displaying the details about a customer, i will create a viewModel called "CustomerViewModel"
public class CustomerViewModel
{
public string CustomerId { set;get;}
public string FirstName { set;get;}
}
Then in my CustomerController, I will have a get method for the customer
public class CustomersController : Controller
{
public ActionResult Details(int id)
{
CustomerViewModel objCustomer=new CustomerViewModel;
objCustomer.FirstName="Samuel";
//Instead of hardcoding the values here , you can get it
// from the database using the id and assign to the properties
return View(objCustomer);
}
}
And you will have a view called "Details.chtml" in your Views\Customer
folder which is strongly typed to your CustomerViewModel
#model CustomerViewModel
<div>
<h2>#Model.FirstName</h2>
<p>#Model.CustomerId</h2>
</div>
This can be accessed like http://yourdomain.com/Customer/Details/25
Personally i prefer to keep my controller actions thin. so i write the GetFromDatabase code in a seperate service layer and i just call that method from my action method
I think that you'll find this article very useful:
MVC Overview
It explains in detail, as to what each component should be used for:
Models. Model objects are the parts of the application that implement
the logic for the application s data domain. Often, model objects
retrieve and store model state in a database. For example, a Product
object might retrieve information from a database, operate on it, and
then write updated information back to a Products table in SQL Server.
Views. Views are the components that display the application s user
interface (UI). Typically, this UI is created from the model data. An
example would be an edit view of a Products table that displays text
boxes, drop-down lists, and check boxes based on the current state of
a Products object.
Controllers. Controllers are the components that handle user
interaction, work with the model, and ultimately select a view to
render that displays UI. In an MVC application, the view only displays
information; the controller handles and responds to user input and
interaction. For example, the controller handles query-string values,
and passes these values to the model, which in turn queries the
database by using the values.
Is there any way of mapping multiple controllers to a single view directory? In my application I would like to have a 1 to 1 mapping between controllers and views. The reason for this is that each view will have a variety of ajax actions that the controller will provide methods for and having multiple views per controller will result in overly large controllers.
Presently I have something like this:
/Controllers
/Dir1Controller
...
/Views
/Dir1
/FirstView.cshtml
/SecondView.cshtml
...
So Dir1 Controller maps to the directory Dir1 and needs to provide all the actions for the views FirstView, SecondView, etc. Instead, I would prefer something like this:
/Controllers
/FirstController
/SecondController
...
Where both controllers map to Dir1 but return the appropriate view when an action is executed.
None of this seems to be a problem on the route mapping side of things but there doesn't seem to be a way for me to tell it how to find the correct view. FirstController will only look in /Views/First for views. Is there any way I can direct it to look in /Views/Dir1?
I looked at using areas but they seem to be directed at spiting up large sites. Conceptually all of these pages should be part of the same area. I just want to keep the size of my controllers bounded.
If your Ajax calls are related to a single controller then stick to the existing pattern and have methods in your controller. If they can be reused put them in partial views or controllers organized by their purpose and when doing your Ajax calls simply request the controller and action. This is the typical pattern for a reason, why step outside of it? :)
Why not just return the view explicitly?
return View("~/Controllers/FirstController/view.cshtml");
If all the actions in a controller return the same view, use a constant at the top of the Controller class, something like:
public class myController
{
private string ViewPath = "~/Controllers/FirstController/view.cshtml";
...
That way you only have to set the path to the view once in each controller. Then in each of your action methods:
return View(ViewPath);