RouteUrl in class - asp.net-mvc

How can I generate a URL by RouteName outside of a view or controller?
I want generate a URL by RouteName in a seperate class for an e-mail, but if I try to use UrlHelper.GenerateUrl. Then I don't see where I can get rest of the parameters for this function.

How i can generate URL by RouteName outside view or conroler ?
You shouldn't be needing/doing this. Urls should be generated only in the front layers where you have access to an HTTP context and passed to backed layers as arguments.
Of course you could always perform some horrible grotesque hack in your backend layer and hardcode some static HttpContext.Current in order to instantiate an UrlHelper and thus render your backed layers strongly coupled to the HTTP stack, making it impossible to be reused in isolation and unit tested.
Oh and by the way checkout MvcMailer if you need to send emails in your application. This way you can define the email body as templates where you will have access to helpers and stuff and won't need to perform the aformentioned grotesque hack.

Related

Can I pass data directly from GET to POST serverside for Create() methods in MVC4 Controllers?

Based on another question:
Creating a Child object in MVC4 - Parent's information not being passed to Create() controller
Does MVC provide a mechanism to send data from the HttpGet Create() to the HttpPost Create() without going through the client? If I need to send some data to the Post method that is meaningless to the client, how can I avoid cluttering the Views and over-exposing model properties to potential attackers?
Your GET and POST actions are just methods on a class. It really doesn't sound like there's any reason to use POST here, if your only concern is to execute a block of code under certain conditions.
Change your POST (drop the attribute) and make it a private method so it is inaccessible to the client. In your GET, do whatever checks you need to do, then invoke the method.
If you do need to expose the POST, refactor the code in question out to a seperate private method that you can call from either GET or POST. A better implementation would be a separate class with the method located there for reuse/testing/SoC.
Just a caution if you are working with a DB here...while there are some legitimate reasons to write to the DB during a GET, note that this is not the indempotent nature of the GET in most circumstances (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html).
Cheers.
Yes - as I mentioned in the other answer you can use TempData - however you don't need this. You are using nothing but an id and a name from your entity, just pass only those in the view model. You don't need the full entity.
On the server side ensure your user has access to those records. For example if I was editing a Customer record, I'd ensure the current user has access via something like:
var currentUsersCompanyId = GetCurrentUserCompanyId();
ctx.Customers.Single(o=>o.CustomerId = customerId and currentUsersCompanyId == customerId)
There are a variety of ways to do this based on how you control permissions - and third party platforms for .net such as Apprenda that help do this more automatically behind the scenes.

Render views without any controller in Play

I am building an application using Play for Model and Controller, but using backbone.js, and client side templating. Now, I want the html templates to be served by Play without any backing controller. I know I could put my templates in the public directory, but I would like to use Play's templating engine for putting in the strings in my template from the message file. I do not need any other data, and hence dont want the pain of creating a dummy controller for each template. Can I do this with Play?
You could create a single controller and pass in the template name as a parameter, but I am not sure if it is a good idea.
public static void controller(String templateName) {
// add whatever logic is needed here
renderTemplate("Controller/"+templateName+".html");
}
Then point all your routes to that controller method. Forget about reverse routing, though.
I think I would still rather have a separate controller method for each template. Remember that you can use the #Before annotation (see Play Framework documentation) to have the message string handling in exactly one place, that is executed before each controller method. By using the #With annotation you can even have this logic in a separate class.
You can use template engine from any place in your code:
String result = TemplateLoader.load("Folder/template.html").render(data);

Sending a parameter to the controller in ASP MVC 2

I am writing an area for administering several subsites, almost all of the functionality will be the same across each site (add/edit/remove pages etc) and my repository on instantiation takes the SiteIdentity so all the data access methods are agnostic in relation to this. The problem I have at the moment is trying to make my action methods also agnostic.
The URL pattern I want to use is along the lines of:
"ExternalSite/{identity}/{controller}/{action}/{id}"
A naive approach is to have each action take the identity parameter, but this means having to pass this in to my repository on each action as well as include it in the ViewData for a couple of UI elements. I'd much rather have this something that happens once in the controller, such as in its constructor.
What is the best way to do this? Currently the best I can come up with is trying to find and cast identity from the RouteData dictionary but part of me feels like there should be a more elegant solution.
It sounds like you want to use OnActionExecuting or a Custom ModelBinder to do that logic each time you have a specific parameter name (also known as a RouteData dictionary key).
Creating a custom modelbinder in ASP.NET MVC
Creating an OnActionExecuting method in ASP.NET MVC, Doing Serverside tracking in ASP.NET MVC
You have access to your route values in Request.RequestContext.RouteData, so you can make base controller and public property SiteIdentity, in such case you can access it from all actions in all inherited controllers.

How to get started with multi-tenant MVC application

I have searched for examples and found several but they are whole large projects. I am looking for some sample on how to get started building an MVC multi-tenant application. I think, the first part would be to decipher the url.
In ASP.Net this is how I did it. I got this from looking at DNN code. How would I do the same in MVC?
Global.asax
private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
string domainName = string.Empty;
// domaName now contains 'example' if application.Request was www.example.com
domainName = GetDomainName(application.Request);
// Using domain, get the info for example from the database
object myPortal = // get from database
// Save in context for use on other pages
context.Items.Add("PortalSettings", myPortal);
}
Then in my basepage I get the value from the context.
I think an even more robust means would be to define a custom route. In that custom route is where you extract the domain and put it into the route values.
You then can have the base controller (as Josh described) which defines a Domain property or the like and stores that value there for convenience (or just extracts it on demand; either way).
By pulling it into the route values up front like that, you can make use of that information anywhere in the app along the request path, not just in the controller, so you get more re-use out of it that way. You can, for example, make use of it in a custom Authorize-like filter to handle the user's rights to that domain, and so on.
Get the domain name. You are on the right track with the DNN code. Just poke around the Request static variable in the debugger; there's all kinds of cool stuff there.
You'll probably need a user store. I use a custom database, but you could use the Microsoft membership provider and profile provider. Make the domain a property of the user, or a property of an organization, and the organization a property of the user.
Store the user's domain in the cookie, encrypted. Read the cookie at the beginning of the request, and make the user has access to that org/domain.
Make a BaseController that extends Controller, then have all your controllers inherit from it. In the BaseController, override OnActionExecuting. This is a much easier place to do your initial request rigging than the Global.asax.cs's Begin_request, because you can define protected members which will be available form every controller.

lessons learned or mistakes made when using asp.net mvc

what are your top lessons learned when starting asp.net mvc that you would highlight to someone starting out so they can avoid these mistakes?
Use Html.Encode() everywhere you print data, unless you have a very good reason to not do so, so you don't have to worry about XSS
Don't hardcode routes into your views or javascripts - they're going to change at some point, use Url.Action() instead
Don't be afraid of using partial views
MVC is no silver bullet, first evaluate if it's indeed the best tool of choice for solving your problem.
Don't forget the "Unit Tests" part of the pattern.
Try to always use a ViewModel to pass data between the Controller and the View.
You may think you don't need one, you can just pass your model around, but suddenly you need a list box with several options for editing a model, or displaying a message (not validation message) and you start adding items to the ViewData, with magic strings as keys, making the app harder to maintain.
There are also some security issues that you solve with a ViewModel.
For instance:
class user:
int id
string name
string email
string username
string password
Your view let's the user change his name and email and posts to the action
public ActionResult Edit(User user)
{
--persist data
}
Someone could tamper your form and post a new password and username and you will need to be very careful with the DefaultBinder behavior.
Now, if you use a ViewModel like:
class userEditViewModel:
int id
string name
string email
The problem is gone.
Whenever it is possible make your view typed
Avoid logic in your views
stay away from the HttpContext
Get Steve Sandersons Pro ASP.NET MVC Framework
Debug into the Sourcecode
If you make a Controller method with a different parameter name from id for a single parameter method, you have to make a new route. Just bite the bullet and use id (it doesn't care about the type) and explain it in the comments.
Makes sure you name your parameters with RedirectToAction :
return RedirectToAction("DonateToCharity", new { id = 1000 });
You lose your ViewData when you RedirectToAction.
Put javascript in seperate files, not into the view page
name of the controller :)
unit test Pattern
Don't use the Forms collection, use model binding.
Try not to use ViewData, create a ViewModel.
If you have a loop or an if in your View, write an HTML helper.
Kindness,
Dan
Don't let your controller become a fat one and do too much work. I've seen 1000+ line controllers in the past and it just becomes an absolute nightmare to understand what's going.
Utilise unit testing for your controllers to ensure that dependencies are kept under control and that your code is testable.
Don't get drawn into letting jQuery and fancy clientscript define the behaviour of your application, try and use it as sparingly as you can and let it enhance your application instead.
Use partial views and HTML helpers whenever possible to ensure that your Views do not become unwieldy and a maintenance nightmare.
Use a ViewModel whenever possible.
Use a dependency injection framework to handle your dependencies (MvcContrib has several controller factories, though it's simple enough to roll your own).
Use a different controller for every section of your site (e.g., Home, Account)
Learn how to use ViewData and TempData
Learn what's the use of RenderPartial

Resources