In a solution with many projects, typically you just want to work with one of the projects. You can, of course, collapse all of the projects you're not interested in, but (depending on how many projects you have) that can still leave a lot of lot clutter in Solution Explorer … and the project you're interested in half-way down the list. And the reality is that, from time to time, you're going to have to expand those other projects, which puts all that clutter back into Solution Explorer.
If, however, you right-click on the project you're mostly interested in and select Scope to This, Solution Explorer will switch Solution Explorer to a view that shows your project and nothing else. Now, when you need to get back to the full solutions listing, you just have to click the back button at the top of Solution Explorer. Back in the full version of Solution Explorer, you can return to your scoped, single project view by clicking the forward button right beside the back button.
This is a simpler solution than my previous tip on opening a separate Solution Explorer for individual projects. To begin, using Scope to This, you can only have a single project in a window by itself -- if you scope to another project you lose the scope on any other project. But, while opening multiple Solution explorers is more flexible I bet that, most of the time, scoping to one project is all the solution you need.
Posted by Peter Vogel on 09/29/2015 at 11:19 AM0 comments
Applying role-based security is easy in ASP.NET MVC: Just decorate the relevant action method/controller class with the Authorization attribute, specify the allowed roles, and you're done. Every once in a while, though, I have a case where role-based security isn't enough.
For example, a client needed security to be applied differently depending on whether the current user was in the eastern or western division of the company. We could've duplicated all the roles in the company (EasternManager vs. WesternManager) or tried to find some clever way to combine roles (for example, assign users to an Eastern or Western role in addition to assigning them to the Manager role) and stack authorization attributes on each method. In the end I decided it was just as easy to create my own division-based Authorization attribute.
To create your own Authorization attribute you just need to create a class that inherits from AuthorizeAttribute and override its AuthorizeCore method. Your AuthorizeCore method must return True or False depending on whether you decide the user is accepted or rejected. This example rejects everyone:
Public Class DivisionAuthorization
Protected Overrides Function AuthorizeCore(httpContext As HttpContextBase) As Boolean
If you want to send the user to a custom page of your own (rather than sending the Web server's default 404 page) you can also override the HandleUnauthorizeRequest method and use a redirect method inside the method to specify the controller/action method name that displays your rejection page.
One hint and one caveat before I'm done:
The hint: You can get ASP.NET MVC's opinion on whether the current user is authorized by calling the base AuthorizeCore method, and passing the same parameter that's passed to your AuthorizeCore method.
The caveat: Your AuthorizeCore method must be thread-safe, so you should only use local variables inside of it.
Posted by Peter Vogel on 09/24/2015 at 10:37 AM0 comments
If you've right-clicked on a project in Solution Explorer, you've probably noticed (but haven't used) the New Solution Explorer View choice. Clicking on that choice with a project selected in Solution Explorer opens a new Solution Explorer view that displays just that project. Initially, the new, dedicated view is free-floating but you can dock it anywhere you want, including docking it as a tab beside your "full" Solution Explorer view.
This is a great alternative to scrolling up and down between two projects in a solution: Once you've opened a view dedicated to a project and docked it, you can just click on the tab that displays the project with which you want to work.
There are two disappointments: You can't name the tab (so you end up with multiple tabs called "Solution Explorer"); Visual Studio doesn't remember your dedicated views from one editing session to another (it also drops any dedicated views if, for example, you add a new project to the solution).
You can actually open a new Solution Explorer view dedicated to almost any item in Solution Explorer, but I've only ever found it useful for projects.
Posted by Peter Vogel on 09/21/2015 at 10:56 AM0 comments
Razor's ability to distinguish between code and HTML/text often looks like magic to me. However, like any good magic act, I'm sometimes surprised by the results I get. For example, this code in a View didn't give me the results I expected:
@SalesOrder.CustomerName & " -- unknown"
Instead of getting the customer's name followed by " -- unknown", I got this:
Peter Vogel & " -- unknown"
Razor had decided that my expression ended at the space before my ampersand. Fortunately, to tell Razor where the real end of my expression is, I just have to include the whole expression in parentheses. This code solved my problem:
@(SalesOrder.CustomerName & " -- unknown")
Now I get:
Peter Vogel – unknown
which is precisely what I want.
Posted by Peter Vogel on 09/14/2015 at 10:10 AM0 comments
I find it handy to assemble complex Views from multiple simpler Partial Views. Sometimes, however, the result is a lot of code in my Views (I even did a column about managing that code). But there's another solution: The HtmlHelper's Action helper method, which allows you to call an action method and incorporate the results of that action method into your View.
This code in a View, for example, calls an action method named DisplayCustomer and adds the Partial View returned by DisplayCustomer to the View:
My example is just the simplest way to call your action method -- you can also pass a controller name and an anonymous object with various property values.
Using the Action method lets you put much of your View-related logic where it belongs: in a method in your controller and not in your View (in the MVC design pattern, Views should have no logic at all). And, of course, once your logic is in a controller method, you can test it.
You probably don't want anyone invoking one of these action methods directly. You can tell ASP.NET MVC not to let that happen by decorating your action method with the ChildActionOnly attribute, like this:
Function DisplayCustomer() As ActionResult
Posted by Peter Vogel on 09/04/2015 at 10:34 AM0 comments
If you do anything at all with file path, you need the Path class (in the System.IO namespace). The methods on the Path class that you're most likely to use include:
- GetTempFileName: Doesn't just return a filename that's guaranteed to be unique -- it also creates the file in the TEMP folder so you can start writing to it
- GetFileName: Returns the file name from a path (and returns null if the path is just the path to a folder without a file name)
- GetDirectoryName: Passed a file path, pulls out the full path to the folder without the closing backslash. One warning: this method returns null if passed the root folder ("c:\")
- Combine: Puts a set of strings together to create a valid file path. Combine will add or remove backslashes as necessary, so the method will do the right thing with the path return by GetDirectoryName
These are the answers; any more questions?
Posted by Peter Vogel on 08/24/2015 at 10:18 AM0 comments
You can tell that the Visual Studio team recognizes the primary issue C# developers face: finding the matching bracket. That must be true because the most obvious way of finding "the other bracket" is built into the way code is displayed: When you put your cursor beside one bracket (open or close), both it and the matching bracket are highlighted (or, because the default color for the brackets is gray: lowlighted).
Unfortunately, that isn't much help if the "matching" bracket is off the screen: you can't see the highlighting if the bracket isn't visible. In those situations my fallback method used to be the plus/minus signs in the left hand margin of the editor window: I collapsed my C# methods to see what code disappeared and what code remained visible. The problem here, of course, is that the collapsed code was often the code in which I was interested.
There's a third option that not a lot of developers know about: Place your cursor on the bracket you're trying to match (open or close) and press Ctrl+] (that's the Control key with a closing square bracket). Your cursor moves to the matching bracket. Pressing the key combination again takes you back to the bracket on which you started.
There are other benefits: If you're bored and stuck on a problem, I've found repeatedly pressing Ctrl+] and watching the cursor snap back and forth can be soothing. And, if anyone is watching, it looks like you're working.
Posted by Peter Vogel on 08/19/2015 at 9:57 AM0 comments
Developers frequently want to ensure two strings are identical without having to worry if some characters are in uppercase in one string and the same characters are in lowercase in the other string. Frequently, you see developers using either ToUpper or ToLower to avoid the problem:
If Name.ToUpper = OtherName.ToUpper Then...
But both ToUpper and ToLower create new strings, which is extra (and unnecessary) work.
If you can live with some extra typing, you can avoid generating those new strings by using the Equals method that every variable has, passing the InvariantCultureIgnoreCase choice from the StringComparison enumeration:
if (Name.Equals(OtherName, StringComparison.InvariantCultureIgnoreCase))
Now you have much less to worry about.
Posted by Peter Vogel on 08/12/2015 at 10:20 AM0 comments
The is keyword lets you check if a variable is pointing to an object of a particular class (or a class that inherits from some class). For example, the code in this if block only executes if CustomerVariable is pointing at an object of type Customer (or some class that inherits from Customer):
if (CustomerVariable is Customer)
...code to execute...
It works with interfaces, too:
if (CustomerVariable is ICustomer)
...code to execute ...
You can do your test and get a free cast from a variable by using the as keyword. If the cast fails, no exception is raised, but your destination variable is set to null, telling you that the variable isn't compatible with the object. The following code not only does what the previous code did, but also casts whatever object PremiumCustomerVariable is pointing to into CustomerVariable (if CustomerVariable and the object are compatible, of course):
CustomerVariable = PremiumCustomerVariable as Customer;
if (CustomerVariable != null)
...code to execute if PremiumCustomerVariable could be cast as a Customer...
If you want to do the same thing using the variable's class (rather than using some object as the previous examples did) then you want to use IsAssignableFrom:
CustomerVariable = PremiumCustomerVariable;
This also works with interfaces:
ICustomerVariable = PremiumVariable;
What other ways do you use to check? Share in the comments section.
Posted by Peter Vogel on 08/04/2015 at 9:03 AM0 comments
I suspect I'm like most developers and keep Visual Studio open and maximized all day (in fact, I've written at least one tip about how to get even more room to edit code). But, I admit, sometimes I switch to other programs. And sometimes, when switching between windows isn't good enough, I need to see that other window beside my Visual Studio window.
You could fiddle with your mouse and window borders. Or, you could hold down the Windows key and press the left arrow button (win_left). The current window will be moved to one side of your screen, have its height set to the full height of your screen and its width set to half of the screen's width. If you switch to another window and press win_left the same thing will happen to that window -- but it will be moved to the other side of your screen so that the two windows display side-by-side. If a window was in maximize mode, it will be taken out of it.
As you might suspect, other combinations of the Windows key and the arrow keys do interesting things. If you press win_up, the current window will be maximized. Both win_right and win_down take the window back to its prior "non-maximized" state (and that half-window display that win_left put you in doesn't count as your prior "non-maximized" state).
And, yes, I realize this isn't really a Visual Studio tip since it works with every window.
Posted by Peter Vogel on 07/30/2015 at 1:06 PM0 comments
I admit it: I don't use the Watch window much. When I hit a breakpoint and want to know what the current value is in a variable that's near the breakpoint, I'll either type "?variableName" in the Immediate window or hover my mouse over the variable to have Visual Studio pop up a Data Tip with the variable name and value.
If you're a "hover your mouse" kind of person you should pay attention to the pushpin at the end of the Data Tip: If you click on the pushpin and switch it to the "upright" position, that Data Tip will stay on the screen. The next time you hit the breakpoint (actually, whenever you have that part of your code on the screen) the Data Tip will be there, displaying the current value of the variable. If you need to drill down into the variable, you can use the plus sign (+) at the beginning of the Data Tip to see the values on the item's properties.
You can do more with your Data Tip: When you hover your mouse over the Data Tip, a "mini-menu" of choices will appear just past the end of the Data Tip. The middle icon in this mini-menu will let you unpin the tip which does not, as you might expect, cause the tip to disappear. Instead, the tip just drifts off to the right and now appears whenever you hit a breakpoint in any code window. This can be very helpful when you're trying to check one variable's value against another or want to change the value of the variable in the Data Tip. The bottom option in the mini-menu, which lets you leave a comment to yourself, can also be useful if your memory is as bad as mine.
The Debug menu also has some choices for managing Data Tips (including exporting and importing Data Tips if you want to keep some around after your debugging session ends). Data Tips are not an unalloyed blessing, if you have long variable names (names are usually displayed with their complete namespace): If the name disappears off the right side of your screen you won't get a scroll bar that will let you move to the right.
Posted by Peter Vogel on 07/23/2015 at 9:43 AM0 comments
Within an Action method, you'll sometimes realize that the processing you need is in some other Action method, often in the same controller. ASP.NET MVC provides a couple of ways of transferring control from one Action method to another one, but, sometimes, the simplest solution is just to call the other method. In those cases, it's worthwhile to remember that when you call the View method in ASP.NET MVC, you're not actually processing a View. The View method merely creates a ViewResult object that, when you return it to ASP.NET MVC, causes ASP.NET MVC to find the View and process it.
In a recent project, many of my controller methods ended by redisplaying the initial page. I had already created a View that did that: It was the first View that's displayed by the controller (I called the Action method that delivered the View FirstDisplay). That method looked like this:
Public Function FirstDisplay (id As Integer?) As ActionResult
...code to load the result object with the data to display...
Return View("DisplayItem", result)
In my other methods, I could just call FirstDisplay to redisplay the page. FirstDisplay would return the ViewResult object with the correct data, so I just had to return the results of FirstDisplay to get the page I wanted:
Public Function Update (id As Integer?) As ActionResult
...code required by the action method...
See? Recycling is good.
Posted by Peter Vogel on 07/15/2015 at 10:55 PM0 comments