Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
mortarr
Apr 28, 2005

frozen meat at high speed
I've got a database I'm connecting to using LinqToSql, and I'm trying to write a unit tests for adding a new user, which involves conditional inserts to several tables and a couple of calls to a stored proc. The code below is a close approximation as I don't have the actual code to hand. I'm writing c# 4 in VS2010, with TestDriven.Net, NUnit and Moq.

I want to test ClassUnderTest.AddNewDatabaseUser(), but I can't really work out how to state what I want to test here... After a successful call PersonRepository.context should contain one new Person object and a PersonGroup object will exist, but it might not have been created by the call.

I think I can test this with Moq, by creating a mock IPersonRepository, using it to make PersonGroupExists() return true or false and having one test per result - is this the right way to test AddNewDatabaseUser()?

I'm also not sure how to test PersonRepository.CreatePerson(), because I do want to test that the person object was created as expected and that the correct int was returned, but I don't want to test the LinqToSql InsertOnSubmit() or SubmitChanges() methods and I don't want this to be an integration test - is there a way to test this kind of method that I can run using testdriven.net?

I've read about pex/moles and TypeMock, because on the face of it they seem like tools that might help mocking the datacontext. I don't want to use Typemock (I can't justify the cost), so I looked into moles but I don't have the experience to know if moles is even a good idea here.


code:
public class ClassUnderTest
{
  private readonly PersonRepository personRepository;

  public ClassUnderTest() : this(new PersonRepository())
  {
  }
  
  public ClassUnderTest(IPersonRepository personRepository)
  {
    this.personRepository = personRepository;
  }
  
  public void AddNewDatabaseUser(string name, int groupId)
  {    
    var personId = this.personRepository.CreatePerson(name, groupId);
    
    if (!PersonGroupExists(groupId, personId))
    {
      this.personRepository.CreatePersonGroup(groupId, personId);
    }  
  }
}

public interface IPersonRepository
{
  int CreatePerson(string name, int groupId);
  
  void CreatePersonGroup(int personId, int groupId);
  
  bool PersonGroupExists(int personId, int groupId);
  
  int GetNextId();
}

public class PersonRepository : IPersonRepository
{
  private readonly DataContext context = new PersonDataContext(); // LinqToSql data context

  public int CreatePerson(string name, int groupId)
  {
    var id = this.GetNextId();
    var person = new Person
      {
        ID = id,
        NAME = name,
        PRIMARY_GROUP = groupId
      }
      
    this.context.Person.InsertOnSubmit(person);
    this.context.SubmitChanges();
    
    return id;
  }
  
  public void CreatePersonGroup(int personId, int groupId)
  {
    var pg = new PersonGroup
      {
        GROUP_ID = groupId,
        PERSON_ID = personGroup
      }
      
    this.context.PersonGroup.InsertOnSubmit(pg);
    this.context.SubmitChanges();    
  }
  
  public bool PersonGroupExists(int personId, int groupId)
  {
    this.context.PersonGroup.Any(pg => pg.GROUP_ID == groupId && pg.PERSON_ID == personId);
  }
  
  public int GetNextId()
  {
    return this.context.GetNextSystemId();
  }
}

mortarr fucked around with this message at 20:02 on Jun 7, 2012

Adbot
ADBOT LOVES YOU

mortarr
Apr 28, 2005

frozen meat at high speed

LOOK I AM A TURTLE posted:

helpful stuff...

Well, it looks like there's a level of detail to testing I've overlooked - I was focussed on the ClassUnderTest.AddNewDatabaseUser() method and kind of overlooked the repository stuff.

I think most of that seems easy to do - writing AddNewDatabaseUser is about as far as I'd got on the db side of this project, so I have no buy-in yet to a particular way of doing things.

The next question is how to go about mocking the datacontext. How do you approach this for EF?

mortarr
Apr 28, 2005

frozen meat at high speed
I found a couple of posts about using a proxy linqToSql data context class and table interfaces/fakes which I have been trying out in the mean time:

http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx
http://krisscott.net/archive/2008/07/14/use-a-generator-to-test-that-pesky-datacontext.aspx


uXs posted:

EF unit testing stuff...

Dromio posted:

There are a few things to deal with when using unit tests with linq2sql...

Thanks for that - I've been using LinqToSql because I'm familiar with it, but I might read up a bit more on EF because it sounds like there's less work writing tests against it. I've used T4 templates before, so I'm not against that either.

mortarr
Apr 28, 2005

frozen meat at high speed
Has anyone read Dependency Injection in .NET by Mark Seemann?

I'm new to DI / IoC and am looking for some sort of real-world guide to point me in the right direction.

mortarr
Apr 28, 2005

frozen meat at high speed

Sagacity posted:

Yes, it's a good book. You do have to know when to stop following its advice though, since it takes DI to a hardcore extreme. For instance, Seemann argues that logging is a cross-cutting concern and therefore should be completely transparent in your application. He suggests you only log which methods you invoke and you do this through a decorator. This is well and good and neatly avoids an ILog dependency in your classes, but it also makes your logging pretty useless in all but the most contrived/academic scenarios.

I've got the unit testing book, although I'm pretty lazy at getting unit tests written. I came onto the DI book after trying to work out how to implement logging without clogging down my methods with a lot of boilerplate stuff - I used the log4net/postsharp library years ago when postsharp was free, so thought I could just do that again.

But because postsharp isn't free anymore, I'm taking a deeper look at DI - it sounds like I've implemented some kind of bastard DI from what I've read so far, so I think it will be good to take a more coherent approach.


A couple of kind-of separate questions:
What is the state of the art in logging without cluttering methods with similar kinds of code? At the moment I'm using log4net to log the method name and any parameter if its basic type like string, int etc, plus extra commentary in complex methods so when debugging it leaves a trail of how I got to the bit that failed. I'm also using elmah for MVC to get a log of the error the end user sees separate to the log file.

My goal with logging at the moment is debugging on the server, but I'm not really sure how to approach logging in production - I certainly don't want as much info in the logs as when I'm debugging, but how do you decide what to log at the "info" level?

mortarr
Apr 28, 2005

frozen meat at high speed
Did I hear something about VS2012 Ultimate being part of a package deal with one of the Team Foundation Server options? Anyone got more info on that?

mortarr
Apr 28, 2005

frozen meat at high speed
I'm using Autofac as my DI tool in an MVC project, and now I need to make a new command line interface and an integration test harness that will both be using pretty much the same registration/config code.

I've been looking at the log4net LogInjectionModule, which looks like it might help, but I can't work out how to apply that approach to my situation.

Is there a standard way to package up the config for reuse somehow, so I'm not repeating it across the three projects?

mortarr
Apr 28, 2005

frozen meat at high speed
Has anyone built custom reports over TFS / TFS Express - I'm looking to find out stuff like:
- How many solutions we have
- What version of VS was used to create the solution (eg. VS05, VS08 BIDS, VS10)
- How many projects the solutions have
- What .net frameworks those projects are addressing (eg. 2, 3.5, 4, 4.5)

I'm doing some investigation into upgrading my teams development environment/toolset to VS12 / some kind of source control that isn't sourcesafe, and trying to get a handle on the size of the problem... I've got a copy of the VSS db moved into TFS express to play around with, but I'm struggling to make any headway on the analysis. If TFS express is no good, I think there is a 90-day eval option for TFS full which I can use.

If there's an SQL query, custom reports, or code anyone has that answer those questions I'm keen to hear about it.

mortarr
Apr 28, 2005

frozen meat at high speed
Can anyone give me some pointers on how to work out what parts of my code are CPU-intensive?

I've got an ASP.Net MVC site that builds word documents based on info from a couple of databases, some images from the filesystem, and subsets of pages from tiffs or pdfs in a document management system. The docs end up between 20mb and 200mb in size, with rare ones peaking at 600mb.

When I run the process from the debugger on my pc, which is a Win7 64bit, 4-core, with 8gb ram, in task manager I can see all 4 cpu's spiking between 20-40% usage (memory seems relatively static before/during/after) - I can do other tasks just fine, and don't notice the hit.

When I run the same operation on my dev server from IIS, which is a virtualised Server 2008 R2 std 64bit, 1-core with 2gb ram, the cpu maxes out at 100% and the server slows to a crawl. If I add another cpu to the server, it's usable, but both cpu's spike between 40-60%.

Ideally I'd like to get the code to play nice on a single-cpu server, but the codebase is big enough that I'm not familiar with all of it anymore, and I'm hoping there are some tricks to finding the best place to optimise.

mortarr
Apr 28, 2005

frozen meat at high speed

Ithaqua posted:

Profile it. Get an ANTS trial or use the built-in profiler in VS2010/2012. Of course, if you're actually doing reasonably processor-intensive work, your dev environment might just not be powerful enough. A profiler can show you what's eating up your cycles, but it can't tell you that it's already optimized as much as it can be.

Also, if you decide to start optimizing, for the love of god write unit tests before you start refactoring. There's nothing worse than thinking you've really sped things up and then realizing that you broke something in the process.

I think my local dev environment is more powerful than the server at the moment, and I was suprised it was a single-cpu server as well.

I'm almost in two minds about this - profiling .net code isn't a skill I have at the moment, and althought its good on a personal level to improve my skills, I'm wondering if the cost of just adding hardware to the server is a better option than potentially going down a rabbit hole. Like you say, I don't have any objective way to tell if optimisations can be made and how long it would take.

I've got some other red gate tools, so I'll take a look at Ants - got any tips for a profiling newbie?

mortarr
Apr 28, 2005

frozen meat at high speed

NickFendon posted:

code:
PM> Install-Package Microsoft.CompilerServices.AsyncTargetingPack

So will this work in VS2010, or is it VS2012 only?

mortarr
Apr 28, 2005

frozen meat at high speed
I'm trying to deal with a many-many relationship in EF5 where a Driver can be related to one or more Drivers.

Here are my SQL backing tables (simplified), and you would navigate from one Driver to the next using the child Link table (a Driver might have no related Drivers):
code:
Driver (
  [StateDetailId] [int] IDENTITY(1,1) NOT NULL
  [Label] [varchar(20)] NOT NULL
)

Link (
  [LinkId] [int] IDENTITY(1,1) NOT NULL,
  [StateDetailId] [int] NOT NULL, -- The driver you're coming from
  [RelatedStateDetailId] [int] NOT NULL -- The driver you're going to
)
Here's what I've got so far in c#:
code:
  public class Driver
  {
    [Key]
    public int StateDetailId { get; set; }

    public string Label { get; set; }    

    public virtual ICollection<Link> Links { get; set; }
  }

  public class Link
  {
    [Key]
    public int LinkId { get; set; }

    [ForeignKey("Driver")]    
    public int StateDetailId { get; set; }

    [ForeignKey("RelatedDriver")]    
    public int RelatedStateDetailId { get; set; }

    public virtual Driver Driver { get; set; }

    public virtual Driver RelatedDriver { get; set; }
  }

  public class SocEntities : DbContext
  {
    public SocEntities(string nameOrConnectionString) : base(nameOrConnectionString)
    {      
    }

    public DbSet<Link> Links { get; set; }
    public DbSet<Driver> Drivers { get; set; }    
    
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      modelBuilder.Entity<Driver>().HasMany(d => d.Links).WithMany().Map(
        m =>
         {
           m.MapLeftKey("StateDetailId");
           m.MapRightKey("RelatedStateDetailId");
           m.ToTable("Link");           
         });
    }
  }
When I actually go to use SocEntities.Drivers, things blow up and I'm getting an error like "System.Data.SqlClient.SqlException: Invalid object name 'dbo.Link1'."

What I was hoping was for each element of SocEntities.Drivers to have its own collection of Drivers which I can move forward/backward through, and I need to use the existing table (I can alter it if I have to, but can't have EF create it for me). Can anyone see what I'm doing wrong?

mortarr
Apr 28, 2005

frozen meat at high speed

Prefect Six posted:

If it will let me interact with spreadsheets better than the seemingly complicated hacks I've read about on stack overflow, yes?

Maybe I just need to spend the time to figure out the probably small differences between C#and VB and use VBA for messing around with Office.

Not sure what version of office you're targeting, but if you're after using .xlsx, you could always try using SpreadsheetML?

I've used WordML in a web app before and found it easy enough after I got used to the object model, with performance being pretty good too (generating/filling in 100meg+ document templates).

Here's a pretty brief thing I found about the spreadsheet side: link

I don't have the project to hand, so I can't give you the specifics about libraries etc, but if you're interested I'll see what I can dig up.

mortarr
Apr 28, 2005

frozen meat at high speed

Uziel posted:

VS versions / SQL / BIDS stuff...

Any insight would be immensely appreciated.

Regarding the BIDS stuff:

If you do not want to upgrade your SSRS/SSIS stuff to SQL 2012 the next time you need to make a change, then you will need VS2005 + BIDS for SQL05 to deploy to SQL 2005 or VS2008 + BIDS for SQL08 to deploy to SQL2008.

I'm using SQL2012 management studio (or whatever the new name for it is) to manage instances of SQL05 on up. I think if you want to do sql script debugging then your management studio version needs to match the SQL version (as with BIDS), and there might be something similar with the database diagrams, but if you don't care about that then just throw on mgmt studio 2012 and add earlier versions if/when you need them.

As far as I've found, once you've got VS version whatever installed, you can add BIDS or not and the order you do it makes no difference (i.e you can add BIDS 05 after BIDS 08). I don't think versions of sql management studio affect each other or VS either, so they can go on in any order too.

mortarr
Apr 28, 2005

frozen meat at high speed
When debugging in VS, and you mouse-over a string variable, you get a tool-tip with the escaped string and you can right-click to the value, expression etc.

Is there a way I can get a copy of the un-escaped string faster/with less mouse clicks than the methods described here or here?

I'm hoping there is a plug-in that either adds a "Copy Un-escaped Value" option to the right-click menu, or gives the option of toggling VS between showing the escaped and un-escaped string in the tool-tip.

mortarr
Apr 28, 2005

frozen meat at high speed
I'm building an ASP.Net MVC4 data entry page for invoices, and I'm not sure how to handle the detail part of the master/detail view.

My invoices have a customer and some notes, which is just like any other MVC create/edit page, and then I need to add/remove line items - these have some behaviour dictated by a couple of drop downs that cause other fields to show or hide, plus calculate line item price, and then the total price needs to be calculated too.

I'm struggling to find the "standard" way of doing this in MVC - I started out hand-rolling DOM manipulation javascript using D3.js (because I'd used it in a previous project), but then I came across knockout.js as a way to template the line items DOM stuff and behaviour (which seemed a bit easier than hand-rolling)...

I'm getting the feeling that I'm missing something fundamental in MVC, but google isn't being very helpful at the moment, does anyone have any pointers or examples?

mortarr fucked around with this message at 21:43 on Feb 6, 2013

mortarr
Apr 28, 2005

frozen meat at high speed

Ithaqua posted:

Partial views?

I can get editable partial views going with just text boxes, but how would you deal with anything more complex, like parent-child drop downs, calculated fields etc?

mortarr
Apr 28, 2005

frozen meat at high speed
I'm not sure if it's bad form to pimp your own question on Stack Overflow, but I've got one that's been up for a while now and haven't had any responses yet.

I'm trying to get glimpse.log4net working but not having any luck, but before I rip it out and try something else I thought I'd ask here. Here's the first part of my question:

quote:

I'm trying to get Glimpse.Log4Net working in an existing ASP.Net MVC v4 project (in VS2010), following the docs, but although the solution compiles and runs Glimpse and log4net seem to be working correctly, I can't see the log4net stuff in the Glimpse window that I'm expecting and as shown near the end of the page in the 2nd link.

I've got dependancy injection going with Autofac, and I don't think it is interfering because I get entries as expected in the log file.

Can anyone point me in the right direction?

mortarr
Apr 28, 2005

frozen meat at high speed

Just going to shamelessly rip off your FrontEnd.Infrastructure layout style, that's way nicer than my current method of throwing the whole lot under FrontEnd.App_Start in a big old mess.

mortarr
Apr 28, 2005

frozen meat at high speed

Not sure how complex your requirements are, but you might want to read up on searching domains v forests and also about groups and primary groups.

Here's some ADSI scripts with a decent commentary, but the gist is it is possible to override a users' primary group (normally "domain users"), and if that has been done, group.members may not give you all the members you want for all groups in the domain.

The link above mentions this probably only happening if Mac or Posix clients log onto the domain, but it might be worth confirming anyway.

mortarr
Apr 28, 2005

frozen meat at high speed

Ithaqua posted:

Has anyone played with InRelease for deployments yet? It's actually pretty awesome. I've been pimping it pretty hard for work lately, but I legitimately dig the product. It's in the VS/TFS 2013 ALM preview VM.

Do you know when TFS 2013 is due out?

mortarr
Apr 28, 2005

frozen meat at high speed

Funking Giblet posted:

Automapper already supports this out of the box with profiles. Don't implement your own interface.
The following with autofac.

code:
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AssignableTo<Profile>().As<Profile>();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsClosedTypesOf(typeof(ValueResolver<,>)).AsSelf();
builder.Register(c =>
{
    Mapper.Configuration.ConstructServicesUsing(DependencyResolver.Current.GetService);
    var profiles = c.Resolve<IEnumerable<Profile>>();
    foreach (var p in profiles)
    {
        Mapper.AddProfile(p);
    }
    Mapper.AssertConfigurationIsValid();
    return Mapper.Engine;
}).As<IMappingEngine>().SingleInstance();
You can then extend the AutoMapper profile class to do you mapping configs, and use valueresolvers for complex values.
The above will support depending injection in both profiles and valueresolvers.
Inject IMappingEngine.

Can you give me an example of extending the profile class?

Another question kind-of related to Automapper... Hope this makes sense, I'm not sitting at my desk so can't show the real code... What's common practice in ASP.Net MVC for getting data into a bunch of a select lists in an edit view? At the moment, I'm sending the data down in a viewmodel alongside the kind-of like so:

code:
class EditableThingViewmodel
{
	public int ThingId { get; set; }

	public string Description { get; set; }

	public int ItemId

	public Dictionary<int, string> Items { get; set; }
}
In the controller, I get an instance Thing and a list of Item from the db, use automapper to convert both into EditableThingViewmodel, and send it down to the view. In the view, I have an extension method that turns the dict into a SelectList. I'm expecting changes to Description and ItemId from the user.

The view is fine and all, but I don't know if this is a good way to do things - when the user attempts to save the form, it comes back without the dict and if I have to send the viewmodel back to the user, I need to repopulate the dict.

Is there a better way to do this kind of thing? I get the feeling I'm missing something.

mortarr
Apr 28, 2005

frozen meat at high speed

Essential posted:

Does anyone know how to Add and Update Entity objects that aren't part of the dbcontext, without querying the database? I'm uploading a few thousand objects via Json, some will already exist in the database and some will be new. I know that I can Add new ones and that I can Attach existing ones (and change the state to modified), but how can I know which ones need to be added and which ones already exist, without querying for each one? If I have 30K records to check it seems like querying for each one would be really taxing and time consuming.

In case I have to query for each one would the quickest query be to use First/Single and only return 1 column?

Does your destination table have a primary key field? If so, can you guess if it is an insert or update that should be performed by the absence/presence of that value in the JSON?

If not, maybe some of these links about "upserts" might help... Entity Framework 5 replaces delete+insert with update, Take care with EF 4.3 AddOrUpdate Method - this one has an example of the sql generated by AddOrUpdate(), C# extension for executing upsert (MERGE SQL command) in EF with MSSQL. Finally, here's a more general discussion of the MERGE statement in SQL.

mortarr
Apr 28, 2005

frozen meat at high speed

Essential posted:

It looks like most of those involve querying one way or the other, however the MERGE looks like it might have something, but that's way more work than I was hoping this would be.

I would say if you are doing this alot, then it might be worth testing performance of your workflow - if checking for the existance of a record is taking too long when managed from the C# side, then handing the whole process off to SQL via the MERGE statement might be worthwhile. If not, you're probably best to keep the process simple and easy to understand.

mortarr
Apr 28, 2005

frozen meat at high speed

PhonyMcRingRing posted:

Does anyone know if there's a way in MVC to tell the model binder to use a specific value provider for a specific property? ex: I want a value to definitely come from the form post, not the querystring. If the form post does not have the value, I don't want it to default to getting the value from the querystring. I just want it to be null.

You can do this by providing your own modelbinder, which sits in the MVC pipeline between the form being posted and your controller action being called...

A basic ModelBinder. If you need to re-validate your model before you return it to the controller, I think you clear the ModelState using `ModelState.Clear();` and then revalidate using `ModelState.IsValid`.
code:
public class DtRequestModelBinder : DefaultModelBinder
{
  public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
  {
    // Decode the base data - this is handled by the base object, which just maps 
    // data from the request string straight into the new DtRequest object.
    var model = base.BindModel(controllerContext, bindingContext) as DtRequest;
      
    if (model == null)
    {
      return null;
    }

    // Here's how to get the request params
    var data = controllerContext.HttpContext.Request.Params;      

    // fix up your model here.

    return model;
  }
}
Here's one way to make sure the right modelbinder is used (kicked off via dependancy injection) - another way is to explicitly state things on the model class itself, and I think you might be able to set it on the controller method via an attribute as well.
code:
public class CustomModelBinderProvider : IModelBinderProvider
{
  public IModelBinder GetBinder(Type modelType)
  {
    // We just use one provider for all custom modelbinders that fails through to the MVC default modelbinder (the null case).  
    var binderType =
      IfSubClassOrSame(modelType, typeof(DtRequest), typeof(DtRequestModelBinder))
      ?? IfSubClassOrSame(modelType, typeof(JobViewModel), typeof(JobViewModelModelBinder));

    return binderType != null 
      ? (IModelBinder)DependencyResolver.Current.GetService(binderType) 
      : null;
  }

  private static Type IfSubClassOrSame(Type subClass, Type baseClass, Type binder)
  {
    return subClass == baseClass || subClass.IsSubclassOf(baseClass) 
      ? binder 
      : null;
  }
}
I use Autofac, and I like to break my DI into modules per project. Not sure if this is good practice, but it works ok for me.
code:
public class AutofacConfig
{
  public static void Register(HttpConfiguration config)
  {
    var builder = new ContainerBuilder();
    builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly()); // This is the bit that finds and runs all the Module implementations 
    var container = builder.Build();

    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
  }
}

public class WebUiModule : Module
{
  protected override void Load(ContainerBuilder builder)
  {
    var assembly = typeof(WebUiModule).Assembly;

    // Other stuff removed for clarity

    // Model binding
    builder.RegisterType<CustomModelBinderProvider>().AsImplementedInterfaces();
    builder.RegisterAssemblyTypes(assembly)
           .Where(t => t.Name.EndsWith("ModelBinder"))
           .AsSelf();
  }
}
This is ultimately called from global.asax - if you didn't have DI, you can register your modelbinders manually here and do away with the CustomModelBinderProvider class
code:
protected void Application_Start()
{
  // Other stuff removed for clarity
  AutofacConfig.Register(GlobalConfiguration.Configuration);      
}
It feels like a lot of code to do something that should be pretty simple, but it can clean up a lot of crap in your controller methods if you've got some wierd incoming data structure that you want to map or parse into something nice for your app. The modelbinder itself is kind-of finicky, it seems like good practice is to use the default binder to instantiate your model, and then fine-tune it as required.

There are a few different ways to approach how the modelbinder should be written, and how you make MVC use the thing. Here's a post on options for registering modelbinders, and I think this is where my modelbinder provider came from. I couldn't find the references I used to design the modelbinder itself, but here's a primer from MSDN mag that looks OK.

mortarr
Apr 28, 2005

frozen meat at high speed

wwb posted:

...use the [HttpPost] attribute

drat, totally forgot about that!

Good to hear that my approach isn't totally shite though... it took a few refinements and a lot of reading to get to that stage.

mortarr
Apr 28, 2005

frozen meat at high speed

PhonyMcRingRing posted:

I'm sure there's a better way of doing this, like just storing that info in TempData or something, but I'm trying to avoid using session for this.

Sorry, you've just about hit my limit on this part of MVC... I've never used the session etc objects, so can't comment on that area, but is there some way you can abuse the postback mechanism, or use some cunning javascript to do the right thing when submitting the page/form (before a modelbinder would even be involved)?

mortarr
Apr 28, 2005

frozen meat at high speed
Probably a long shot, but does anyone know of an outfit that offers TFS 2013 training in New Zealand (or online from Australia, at a pinch)? I've been looking at Equinox IT but they're dicking me around on dates.

mortarr
Apr 28, 2005

frozen meat at high speed
I'm trying to screen-scrape my local library's site for their weekly list of new books, so I can turn it into an RSS feed or something. Each result has a link that does some kind of javascript post which gets more details about each result item and updates a modal div with the data.

I can parse the main results screen easily enough, but I can't figure out what I need to do to get the POST working properly. I've made up a quick and dirty gist that uses HttpWebRequest and CsQuery to get the first result on the initial results page and parse out the url I need to post to...

Comparing traces in Fiddler between using the browser and using this code, I can see that there are differences but I can't figure out what I need to do to the 2nd request to cause it to get the correct data. Is there something fundamental I'm missing?

mortarr
Apr 28, 2005

frozen meat at high speed

wwb posted:

Any reason you don't just grab the RSS feed from the search link you posted -- there is a "subscribe to feed" butotn above the search results that worked at a cursory glance?

What you are running into is ASP.NET ajax, which let one do some pretty powerful poo poo in it's heyday but it isn't a modern, scrapable HTTP interaction in the least. I can't think of a good way of getting at the data without having a javascript interperter or doing serious reverse engineering but that is possible since they have been releasing the source code to asp.net ajax for a long time -- see http://www.microsoft.com/en-us/download/details.aspx?id=24165 to start with.

Well poo poo, I've got no excuse for missing that!

mortarr
Apr 28, 2005

frozen meat at high speed
Can someone critique the way I configure Automapper and Autofac in an MVC/WebAPI project?

What I'm trying to do is firstly have autofac identify a series of modules across all projects that the MVC project depends on in the solution and register them, one of which does roughly the same for automapper.

I thought it might be a good idea to have all the autofac and automapper config for the project lie in the relevant project itself, so I don't end up with boatloads of config stuff in the MVC project, but I can't work out how to autoscan all dependant assemblies in AutomapperModule.Load() - I've tried AppDomain.CurrentDomain.GetAssemblies() but it doesn't seem to work.

Is this even a sensible thing to do, or should I just throw all my config stuff back in the MVC project?

code:
  // In project 'Orm' (a class library holding repositories and DTO's etc)
  // This project makes heavy use of Automapper, and this method controls the config for the 'Orm' project.
  public class OrmProfile : Profile
  {
    protected override void Configure()
    {
      Mapper.CreateMap<Project, Item>();
      // Lots of mapping code removed...
    }
  }
code:
  // In project 'WebUI' (an MVC project), which has a reference to 'Orm'
  public class AutofacConfig
  {
    // This is called from globabl.asax and scans for all Autofac modules in 
    // the current assembly and loads them, I'd like to make this work for all 
    // dependant assemblies but don't need to right now.
    public static void Register(HttpConfiguration config)
    {
      var builder = new ContainerBuilder();
      builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());
      var container = builder.Build();

      DependencyResolver.SetResolver(new AutofacDependencyResolver(container));      
      GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);      
    }
  }

  // Also in project 'WebUI' 
  public class AutomapperModule : Module
  {
    protected override void Load(ContainerBuilder builder)
    {
      // I want to merge this and the below call, but 
      // builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies()).AssignableTo<Profile>().As<Profile>(); 
      // doesn't seem to do what I thought it would.
      builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
             .AssignableTo<Profile>()
             .As<Profile>();

      builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(OrmProfile)))
             .AssignableTo<Profile>()
             .As<Profile>();

      builder.Register(GetMappingEngine).As<IMappingEngine>().SingleInstance();
    }

    private static IMappingEngine GetMappingEngine(IComponentContext context)
    {
      Mapper.Configuration.ConstructServicesUsing(DependencyResolver.Current.GetService);

      foreach (var p in context.Resolve<IEnumerable<Profile>>())
      {
        Mapper.AddProfile(p);
      }

      Mapper.AssertConfigurationIsValid();
      return Mapper.Engine;
    }
  }

mortarr
Apr 28, 2005

frozen meat at high speed

Sedro posted:

AppDomain.CurrentDomain.GetAssemblies will only return assemblies which are loaded at the time, and they are often lazy loaded as part of the IoC container's job.

Try BuildManager.GetReferencedAssemblies.

Thanks, that did the business.

mortarr
Apr 28, 2005

frozen meat at high speed

Gnack posted:

Words about asp.net MVC authentication...

Not sure if this is relevant for your situation, but once you have the info on authentication, I've used fluent security for the authorisation stuff in MVC projects, as a way to record what roles have what access in a centralised location, rather than spread out as attributes over all my controllers etc.

Here's a basic example from their getting started guide...

code:
SecurityConfigurator.Configure(configuration =>
{
	// Let FluentSecurity know how to get the authentication status of the current user
	configuration.GetAuthenticationStatusFrom(() => HttpContext.Current.User.Identity.IsAuthenticated);

	// This is where you set up the policies you want FluentSecurity to enforce on your controllers and actions
	configuration.For<HomeController>().Ignore();
	configuration.For<AccountController>().DenyAuthenticatedAccess();
	configuration.For<AccountController>(x => x.ChangePassword()).DenyAnonymousAccess();
	configuration.For<AccountController>(x => x.LogOff()).DenyAnonymousAccess();
});
I'm using a combination of Active Directory for authentication and SQL for user/role mapping, so membership can be controlled by a super-user of the app (without bothering the IT helpdesk if I had gone with AD roles). It works by injecting role membership into a custom user object, and using fluent security to validate the user/role/controller-method combo, then bailing to an access-denied screen if they're not allowed.

I'm not a pro at MVC security, and this is for an internal app, but it seems to work really well and I found the docs to be pretty good too.

mortarr
Apr 28, 2005

frozen meat at high speed

RICHUNCLEPENNYBAGS posted:

...

But anyway, my point is I would recommend it for people who already know SQL but don't want to bother hand-mapping everything, not people who don't know anything about SQL and are hoping to avoid learning. I'm using Code First though; I guess some of these things might play out differently with DB First.

I'd second this, as a seasoned user of code-first, there's no way I'd let junior devs with or those with no or little SQL experience do anything significant using EF code-first without a senior watching them closely.

I've never used the EF designers and visual modelling tools, and a good third of my EF work deals with maintenance/brown-fields dev in existing inhouse and vendor db's, so can't speak to true green-fields or single-db-only dev situations.

mortarr
Apr 28, 2005

frozen meat at high speed
I'm trying to speed up a process that's caching 300-odd web pages for later analysis, the idea is send in a list of urls and get back a dict of url/page, but I've not done any async stuff and I'm pretty sure I'm doing it wrong - can anyone give me some pointers?

My original code is a for loop, and I was hoping to improve performance by getting several pages at once.


code:
    public Dictionary<string, string> Download(IEnumerable<string> urls)
    {
      var results = new ConcurrentDictionary<string, string>();

      // Create queue of WebClient instances
      var clientQueue = new BlockingCollection<WebClient>();

      // Initialize queue with some number of WebClient instances
      for (var i = 0; i < 10; i++)
      {
        var c = new WebClient { Proxy = WebRequest.GetSystemWebProxy() };
        c.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;

        c.DownloadStringCompleted += (sender, e) =>
        {
          if (!e.Cancelled && e.Error == null)
          {
            var url = (string)e.UserState;
            var content = e.Result;
            results.TryAdd(url, content);
          }

          clientQueue.Add(c);
        };
      }

      // now process urls
      foreach (var url in urls)
      {
        var worker = clientQueue.Take();
        worker.DownloadStringAsync(new Uri(url), url);
      }

      return results.ToDictionary(entry => entry.Key, entry => entry.Value);
    }  

mortarr
Apr 28, 2005

frozen meat at high speed

Crazy Mike posted:

My problem for today: How do I get the source of a Model Validation error?
We start off with:
code:
@Html.ValidationSummary()
And want to build something that scrolls to the input that's not validating.
I can build something like in this stack overflow question.

code:
<table>
         @{foreach (ModelState modelState in ViewData.ModelState.Values)
           {
               foreach (ModelError error in modelState.Errors)
               {
                <tr><td>Fix This!</td><td>@error.ErrorMessage</td></tr>
               }

           }}
</table>
But need to figure out how to get the id so that the cell would be like
code:
<td onclick="scrollTo('@ID???')">
We have something like this in javascript, but instead of adapting that I'm hoping there's some simpler way available.

If I understand you, you're after having a list of validation errors in one part of the page, each with a link to the element that caused the error?

If that's right then each error needs to know a way to reference the input/textarea/whatever element, which should be possible because usually data entry elements created in your view like `@Html.TextBoxFor(m => m.ProjectName)` ends up like `<input id="ProjectName" name="ProjectName" ... />` when rendered.

So if you have some javascript to scroll to a given element, all you'll need is to add an attribute with the id or name of the element causing the error to the element in error itself.

Using `@Html.ValidationSummary(false)` renders as the following, which is pretty unhelpful in your case:

code:
<div data-valmsg-summary="true" class="validation-summary-errors">
  <ul>
    <li>An error message for a field</li>
  </ul>
</div>
Maybe our google-fu is weak because this seems like a handy thing to have, and surely someone has dealt with it before. I couldn't find anything either, so I knocked this up here - I've not really tested it, but maybe it's a start.

The idea is to create something like so when calling `@Html.CunningValidationSummary(...)`:

code:
  <div data-valmsg-summary="true" class="validation-summary-errors">
    <ul>
      <li data-valmsg-source="ProjectName">The project name should not be empty.</li>
    </ul>
  </div>
Then maybe you add an icon into all li's in div.validation-summary-errors and bind clicks on it? I guess there's different ways to proceed from here.

You might also want to check out this, which is where I first saw `htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName` being used.

Adbot
ADBOT LOVES YOU

mortarr
Apr 28, 2005

frozen meat at high speed

Ithaqua posted:

Okay, new OP draft. What books/tools/plugins/resources/etc do you guys want to have in it?

Looks good. Here's some more stuff - is it worth putting nuget packages under frameworks/tools?

Books:
Dependency Injection in .NET (Martin Seeman).

Database stuff:
downloadsqlserverexpress.com. Links to SQL Express install packages, without needing to trawl through MSDN.

VS Plugins:
Nuget. Package management for .Net. Using nuget you can pull 3rd party libraries into your projects using its package manager console without leaving VS.

Frameworks/Tools:
  • Autofac, an IoC container for .Net. Getting started guide.
  • Automapper. AutoMapper is a neat little tool to help mapping one object to another.
  • Elmah (Error Logging Modules and Handlers), an application-wide error logging facility for ASP.Net. Here's a list of guides and articles.
  • FluentValidation, a validation library that uses a fluent interface and lambda expressions for building validation rules for your business objects.

  • Locked thread