TFS2012 allows you to mark builds as deployed, this is meant to work hand in hand with the azure deployment but I figured it should work with whatever TfsDeployer does too.
TFS always seems to throw an error afterwards which i haven't figured out quite yet, so i'm just wrapping it in a try/catch. Even if it didn't throw this exception, I think it will throw another one if you ever try mark the same build as deployed
This adds a new row in the "deployed" tab under builds in TFS 2012 web access (looks like visual studio doesn't support this quite yet).
It has a redeploy button which just triggers a new build, so it won't actually set the correct build quality to be auto deployed by tfs deployer.
Added a discussion to TFS Deployers discussion tab http://tfsdeployer.codeplex.com/discussions/397983
Wednesday, October 3, 2012
Friday, September 28, 2012
TFS 2012 - set user images to be same as active directory
I posted a question on Stackoverflow hoping that someone has an idea of how to use the user image api in tfs 2012.
http://stackoverflow.com/questions/12633732/api-to-update-users-image-identity-extended-properties-not-saving
Update
Figured it out myself
http://stackoverflow.com/questions/12633732/api-to-update-users-image-identity-extended-properties-not-saving
Update
Figured it out myself
Labels:
Stackoverflow,
TFS
Monday, September 24, 2012
TFS 2012 - Groups Reviewed
When the company I work at first started using TFS 2005 we decided to have only one Team Project due to the limit of ~250 Team Projects. Today our root source folder for our main Team Project has a few hundred folders (clients) in it, so do our areas and iteration trees. While it is a bit annoying to maintain, I am certainly thankful of that decision when it comes to upgrading versions of TFS.
So understandably when I heard about the new Team concept in TFS 2012 I got rather excited. After playing with Teams for a little while in 2012 they are nice, but don't help with management as much as I was hoping for.
Things I think should be tweaked
So understandably when I heard about the new Team concept in TFS 2012 I got rather excited. After playing with Teams for a little while in 2012 they are nice, but don't help with management as much as I was hoping for.
Things I think should be tweaked
- Work Items - "Assigned To Me" should filter by current team
- When creating an alert in a team, I should be able to filter work items by my team iteration or areas rather than selecting it manually
- Alerts that can be reused between teams (Email all team members when a work item is created in an area their team is associated to)
- Iteration/Area tree views in the admin section should default to filtered to the default area/iteration and what is below it
- Source view should select the first team favourite
- Builds should filter queued/completed by team favourites
- Easier way to assign security to areas based on groups (eg if a group is assocated to an area then allow the group a particular access level)
- Allow personal favourites per team
- At least some level of integration with reports
- Way to change the path of the area that is automatically created for a team
Obviously the extended view is required to setup favourites in the first place, but this can be a toggle on all views. Nothing major, i just feel that it might be nice to restrict my default view a bit more when I'm meant to be looking at a team.
Maybe i'll look into the plugin framework a bit more and see what I can do.
Labels:
TFS
TFS 2012 - Web Access Plugins
Update 1
Found a blog series on how to write custom work item controls (plugins) in javascript (which is quite old, oops). Custom controls don't seem all that exciting to me, but there may be enough information there to develop something else with the information.- http://blogs.msdn.com/b/serkani/archive/2012/06/22/work-item-custom-control-development-in-tf-web-access-2012-development.aspx
- http://blogs.msdn.com/b/serkani/archive/2012/06/22/work-item-custom-control-development-in-tf-web-access-2012-deployment.aspx
- http://blogs.msdn.com/b/serkani/archive/2012/07/12/adding-content-files-to-work-item-custom-control-extension-package.aspx
Update 2
Tiago Pascoal has released a Plugin that enhances the Task Board
http://pascoal.net/2012/09/team-foundation-task-board-enhancer-version-0-3-released
Update 3
Wrote my own very basic plugin to make the logo a clickable link
http://bzbetty.blogspot.co.nz/2012/11/very-simple-tfs-2012-web-access-plugin.html
While using the new WebAccess for TFS 2012 I noticed an interesting tab in the administration section named extensions, but it appears Microsoft haven't made the API public yet (1) so I thought I might have a quick dig to see what I could figure out. Because the information has not been made public by Microsoft there's a good chance it will all change in upcoming TFS builds.
The Plugins
Plugins appear to be uploaded as a zip file containing an xml manifest file which defines its name, version, vendor and a few other properties. The author can also specify which other modules it loads after suggesting it has some form of dependency management.
All files included in the archive appear to be uploaded to a filestore somewhere, but the only required file that I could see was the manifest.xml. Unfortunately whenever I tried making a extension I got the error message "TF400900: Invalid zip archive file : manifest.zip" upon upload, no resolution as of yet.
Registered plugins are added to a common xml file and serialized to a database or other persistent storage. Neither my TFS_Configuration nor Team Collection databases appeared to contain this file, more than likely it is created when the first plugin is uploaded.
There's a couple of properties and an ActionFilter that make it look like javascript plays a big part of these plugins. The website itself does reference a file named builtin-plugins.js, which then references a bunch of other javascript files by name.
The builtin javascript plugins align very nicely with the areas defined earlier, although not a 1 to 1 mapping.
I curious to see a lack of NuGet, it would have made a great plugin repository as seen in a number of projects now and would have provided a few major benefits such as better dependency management and a distribution channel. Although given Microsoft's recent announcements of other App Stores maybe they plan to take the same route with TFS.
Another point of interest is that TFSPreview does not appear to have this tab, which would be a curious ommision if they are just javascript scripts.
Portable Areas
TFS 2012 also seems to make heavy use of MVC areas, each area defined seems to be separated into its own assembly file containing the relevant controllers, viewmodels and other relevant code. Some form of portable area code must have been developed, although i'm guessing nothing was taken from either MvcContrib nor Orchard.
Interestingly they don't appear to take advantage of the new WebAPI, nor do they use razor for their view engine. But they do typically contain a basic controller for serving views with little logic and an api controller to query via json.
While i haven't had the time to dig into this whole thing properly it looks like it should be possible to create complete new tabs/areas using MVC in the new webaccess, or to augment the existing ones using javascript plugins. Considering how much of the UI appears to be created on the clientside this could be a very powerful little framework. I hope Microsoft start releasing information about it soon, if not I'm sure a blogger will.
References
(1) http://social.msdn.microsoft.com/Forums/en-US/TFSvnext/thread/7696732e-767a-43c7-81d2-c318aeff41ed/
Labels:
TFS
Sunday, June 3, 2012
Using AutoMapper to copy Metadata from Entities to ViewModels
On my crusade to eliminate common mistakes causing bugs in my projects I found was that my metadata on my entities didn’t always match my viewmodels. I wrote 2 fairly simple providers to copy the metadata from the entity to the ViewModel at runtime which leverages my AutoMapper configuration so it supports field names that are renamed.
I use the approach below to automatically copy data annotations from my entities to my view model. This ensures that things like StringLength and Required values are always the same for entity/viewmodel.
It works using the Automapper configuration, so works if the properties are named differently on the viewmodel as long as AutoMapper is setup correctly.
You need to create a custom ModelValidatorProvider and custom ModelMetadataProvider to get this to work. My memory on why is a little foggy, but I believe it's so both server and client side validation work, as well as any other formatting you do based on the metadata (eg an asterix next to required fields).
Note: I have simplified my code slightly as I added it below, so there may be a few small issues.
Metadata Provider
Validator Provivder
Helper Method Referenced in above 2 classes
Other Notes
If you're using dependency injection, make sure your container isn't already replacing the built in metadata provider or validator provider. In my case I was using the Ninject.MVC3 package which bound one of them after creating the kernel, I then had to rebind it afterwards so my class was actually used. I was getting exceptions about Required only being allowed to be added once, took most of a day to track it down.
My StackOverflow Post: http://stackoverflow.com/questions/9989785/technique-for-carrying-metadata-to-view-models-with-automapper/10100042#10100042
Labels:
AutoMapper,
Metadata,
MVC,
Stackoverflow
Dependency Injection for RouteConstraints
Often I've wanted to check whether something exists in the database in a route constraint, unfortunately MVC doesn't support dependency injection for RouteConstraints out of the box, and due to them being alive for the entire life of the application it isn't that easy. If the scope of the dependency is in request scope, for example, then it will work for the first request then not for every request after that.
You can get around this by using a very simple DI wrapper for your route constraints.
then create your routes like this
Pagination with AutoMapper
I recently posted a method of using AutoMapper in an ActionResult (http://bzbetty.blogspot.co.nz/2012/06/thoughts-on-actionfilters.html). This became an issue when I was trying to return a paginated model to the view, as I wanted to do pagination in the database (on the entities) but AutoMapper had no idea how to map the IPagination result to the ViewModel.
Result - Build a custom IObjectMapper to do the mapping
Resulting Action
IObjectMapper
Result - Build a custom IObjectMapper to do the mapping
Resulting Action
IObjectMapper
Labels:
AutoMapper,
MVC,
MVCContrib
Updating collections using AutoMapper
By default AutoMapper replaces child lists with a completely new instance only containing the items in the original list. Because of the way EF works you need to change the existing items in the list for it to track changes as updates instead of adds. This method also means deletes can be tracked succesfully.
Basic steps were
Ensure the destination collection is loaded from db and attached to the object graph for change tracking
.ForMember(dest => dest.Categories, opt => opt.UseDestinationValue())
Then create a custom IObjectMapper for mapping IList<> to IList<T> where T : Entity
The custom IObject mapper used some code from http://groups.google.com/group/automapper-users/browse_thread/thread/8c7896fbc3f72514
Finally one last piece of logic to check all Id's in targetCollection exist in sourceCollection and delete them if they don't.
It wasn't all that much code in the end and is reusable in other actions.
My Stackoverflow Post: http://stackoverflow.com/questions/9739568/when-using-dtos-automapper-nhibernate-reflecting-changes-in-child-collections/9856360#9856360
Recently found a library that does just this - https://github.com/TylerCarlson1/Automapper.Collection My Stackoverflow Post: http://stackoverflow.com/questions/9739568/when-using-dtos-automapper-nhibernate-reflecting-changes-in-child-collections/9856360#9856360
Labels:
AutoMapper,
EF,
Stackoverflow
Thoughts on ModelBinders
Validation
Source: http://www.markeverard.com/blog/2011/07/18/creating-a-custom-modelbinder-allowing-validation-of-injected-composite-models/
Custom ModelBinders don’t seem to run validation on the newly created model automatically, so while you may add validation attributes to your model you need to add in some extra code to force validation to occur.
There may be a class you can override to get this automatically but I haven’t found it yet.
Entities
Source: http://lostechies.com/jimmybogard/2011/07/07/intelligent-model-binding-with-model-binder-providers/
An interesting technique I’ve seen used is using modelbinding to automatically load an entity based on the id passed in. So your actions ask for an entity instead of an Id.
Doesn’t seem like much but it should remove 1 line from most actions (loading the entity from the database). However it requires you to never use your entities as edit models (which you shouldn’t be doing anyway). It also doesn’t allow extra filtering/including of data that I can tell.
This idea could be extended to work on list pages by creating a filter criteria from all route values (page, sort, search)
Dependency Injecting Model Binders
Source: http://iridescence.no/post/Constructor-Injection-for-ASPNET-MVC-Model-Binders.aspx
Out of the box you can’t use dependency injection with ModelBinders, you can however pass objects in when you create them at registration time. If your ModelBinders only take singletons then that approach works, otherwise create a fairly basic modelbinder that takes your kernel as a parameter and when binding method is called use the kernel to create your real model binder complete with full dependency injection.
DateTimes
For a recent projet I didn’t want to use a javascript datetime picker as it was meant to be used on a horrible android tablet, but I still wanted something a bit friendlier than a textbox. I chose to split dates into day/month/year fields, which would be a lot of effort to do to every date manually.
Instead I made an Editor Template for DateTimes which outputs 3 fields, and a custom ModelBinder that when binding dates looks for 3 fields instead of just 1.
Labels:
ModelBinder,
MVC
Thoughts on ActionFilters
UnitOfWork
Source: Ayende/Rob Conery http://wekeroad.com/2011/03/21/using-entityframework-with-aspnet-mvc-3/
I have a very basic UnitOfWork ActionFilter which runs after every action, when no exceptions are thrown it calls SaveChanges on my DbContext (which is set to be 1 per request in ninject). Mostly because we occasionally forgot to call this method.
AutoMapperActionFilter
Source: http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/
Because I use AutoMapper to create my ViewModels from my entities I ended up with a bunch of code in my views that basically looked like
In my crusade to remove repetitive code in my actions, I created an extra ActionFilter that can perform the mapping after the action has finished executing.
The main benefit of this turned out to not be less code, as it’s still the same number of lines of code. It was that my tests no longer needed to setup AutoMapper in order to test an Action (except for the create/update actions).
Jimmy has actually moved on from using an ActionFilter and started using an ActionResult that decorates another ActionResult and performs the mapping. I don’t use that approach as I find it hard/impossible to add code between the mapping and the final view being displayed, which I needed to do to populate dropdowns (see ViewModelEnricher). Jimmy’s new approach looks like the following:
ViewModelEnricher
Source: http://ben.onfabrik.com/posts/better-form-handling-in-aspnet-mvc
Another piece of repetitive code was loading the contents dropdowns and adding them to the ViewModels. I created yet another ActionFilter (run after the AutoMap one) which looks at all the properties on a ViewModel for an attribute telling it where to load dropdowns from.
This was added globally to all actions and meant I could no longer accidentally forget to add the code to set the dropdowns on Validation failure of an update/create action (most common place to forget to do it).
I’m still not 100% convinced this is the best approach; I’ve been playing with the concept that dropdowns are dependencies of the ViewModel and should be created by the DI container. This would either require the AutoMap ActionFilter and ModelBinder to create all ViewModels using the DependencyResolver or a small modification to the ViewModelEnricher ActionFilter to use property injection into an existing object on the way through.
ValidationActionFilter
Source: http://trycatchfail.com/blog/post/Cleaning-up-POSTs-in-ASPNET-MVC-the-Fail-Tracker-Way.aspx
It’s fairly common to check ModelState.IsValid on all postbacks and return a view if validation fails. I added another global action filter which performs this check on any post request. Again this is so it isn’t accidentally forgotten and to reduce the amount of repetitive code in Actions.
Labels:
ActionFilter,
MVC
Subscribe to:
Posts (Atom)