I have almost exactly the same scenario described by Nathon Taylor in ASP.NET MVC - Sharing Session State Between Controllers. The problem is that if I save the path to the images inside a Session variable List<string>
it is not being defined back in the ItemController so all the paths are being lost... Here's my setup:
Inside ImageController I have the Upload() action method:
public ActionResult Upload()
{
var newFile = System.Web.HttpContext.Current.Request.Files["Filedata"];
string guid = Guid.NewGuid() + newFile.FileName;
string itemImagesFolder = Server.MapPath(Url.Content("~/Content/ItemImages/"));
string fileName = itemImagesFolder + "originals/" + guid;
newFile.SaveAs(fileName);
var resizePath = itemImagesFolder + "temp/";
string finalPath;
foreach (var dim in _dimensions)
{
var resizedPath = _imageService.ResizeImage(fileName, resizePath, dim.Width + (dim.Width * 10/100), guid);
var bytes = _imageService.CropImage(resizedPath, dim.Width, dim.Height, 0, 0);
finalPath = itemImagesFolder + dim.Title + "/" + guid;
_imageService.SaveImage(bytes, finalPath);
}
AddToSession(guid);
var returnPath = Url.Content("~/Content/ItemImages/150x150/" + guid);
return Content(returnPath);
}
private void AddToSession(string fileName)
{
if(Session[SessionKeys.Images] == null)
{
var imageList = new List<string>();
Session[SessionKeys.Images] = imageList;
}
((List<string>)Session[SessionKeys.Images]).Add(fileName);
}
Then inside my ItemController I have the New() action method which has the following code:
List<string> imageNames;
var images = new List<Image>();
if (Session[SessionKeys.Images] != null) //always returns false
{
imageNames = Session[SessionKeys.Images] as List<string>;
int rank = 1;
foreach (var name in imageNames)
{
var img = new Image {Name = name, Rank = rank};
images.Add(img);
rank++;
}
}
Ok so why is this happening and how do I solve it?
Also, I was thinking of whether I could move the ActionMethod that takes care of the upload of the images into the ItemController and store the image paths inside a List property on the ItemController itself, would that actually work? Note though, that images are being uploaded and taken care of via an AJAX request. Then when the user submits the item entry form, all the data about the Item along with the images should be saved to the database...
Update:
I've updated the code. Also I think I should add that I'm using StructureMap as my controller factorory. Could it be a scoping issue? What is the default scope that is usually used by StructureMap?
public class StructureMapDependencyResolver : IDependencyResolver
{
public StructureMapDependencyResolver(IContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
if (serviceType.IsAbstract || serviceType.IsInterface)
{
return _container.TryGetInstance(serviceType);
}
else
{
return _container.GetInstance(serviceType);
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.GetAllInstances<object>()
.Where(s => s.GetType() == serviceType);
}
private readonly IContainer _container;
}
And inside my Global.asax file:
private static IContainer ConfigureStructureMap()
{
ObjectFactory.Configure(x =>
{
x.For<IDatabaseFactory>().Use<EfDatabaseFactory>();
x.For<IUnitOfWork>().Use<UnitOfWork>();
x.For<IGenericMethodsRepository>().Use<GenericMethodsRepository>();
x.For<IUserService>().Use<UsersManager>();
x.For<IBiddingService>().Use<BiddingService>();
x.For<ISearchService>().Use<SearchService>();
x.For<IFaqService>().Use<FaqService>();
x.For<IItemsService>().Use<ItemsService>();
x.For<IMessagingService>().Use<MessagingService>();
x.For<IStaticQueriesService>().Use<StaticQueriesService>();
x.For < IImagesService<Image>>().Use<ImagesService>();
x.For<ICommentingService>().Use<CommentingService>();
x.For<ICategoryService>().Use<CategoryService>();
x.For<IHelper>().Use<Helper>();
x.For<HttpContext>().HttpContextScoped().Use(HttpContext.Current);
x.For(typeof(Validator<>)).Use(typeof(NullValidator<>));
x.For<Validator<Rating>>().Use<RatingValidator>();
x.For<Validator<TopLevelCategory>>().Use<TopLevelCategoryValidator>();
});
Func<Type, IValidator> validatorFactory = type =>
{
var valType = typeof(Validator<>).MakeGenericType(type);
return (IValidator)ObjectFactory.GetInstance(valType);
};
ObjectFactory.Configure(x => x.For<IValidationProvider>().Use(() => new ValidationProvider(validatorFactory)));
return ObjectFactory.Container;
}
Any thoughts?