Переменные сеанса, потерянные между контроллерами и методами действий - PullRequest
6 голосов
/ 01 мая 2011

У меня почти точно такой же сценарий, который описан Натоном Тейлором в ASP.NET MVC - Совместное использование состояния сеанса между контроллерами .Проблема в том, что если я сохраняю путь к изображениям внутри переменной Session List<string>, она не определяется обратно в ItemController, поэтому все пути теряются ... Вот мои настройки:

Внутри ImageControllerУ меня есть метод действия Upload ():

    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);
    }

Тогда внутри моего ItemController у меня есть метод действия New (), который имеет следующий код:

        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++;
            }
        }

Хорошо, так почему этопроисходит и как мне это решить?

Кроме того, я думал о том, могу ли я переместить ActionMethod, который заботится о загрузке изображений в ItemController, и сохранить пути к изображениям внутри свойства List в самом ItemController, будет ли это работать на самом деле?Обратите внимание, что изображения загружаются и обрабатываются с помощью запроса AJAX.Затем, когда пользователь отправляет форму ввода элемента, все данные об элементе вместе с изображениями должны быть сохранены в базе данных ...

Обновление:

Iобновил кодТакже я думаю, что должен добавить, что я использую StructureMap в качестве фактора контроллера.Может ли это быть проблемой?Какова область по умолчанию, которая обычно используется 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;
}

А внутри моего файла Global.asax:

    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;
    }

Есть мысли?

Ответы [ 3 ]

12 голосов
/ 10 июня 2011

Я только что добавил это в Global.asax.cs

   protected void Session_Start()
   {
   }

Похоже, это решило проблему. Я установил точку останова, которая получает удар только один раз за сеанс (как и ожидалось).

2 голосов
/ 01 мая 2011

Одной из возможных причин этого является то, что домен приложения перезапускается между первым и вторым действиями и, поскольку сеанс хранится в памяти, он будет потерян.Это может произойти, если вы перекомпилируете приложение между ними.Попробуйте установить точки останова в обратных вызовах Application_Start и Session_Start в Global.asax и посмотрите, не вызваны ли они дважды.

0 голосов
/ 01 мая 2011

Используете ли вы когда-либо кроме доступа к HttpContext.Current прямо в своем коде? Другими словами, есть ли места, где вы вводите HttpContext ради насмешки в юнит-тестах?

Если вы обращаетесь к нему только в своих методах, то нет причины иметь запись x.For<HttpContext>().HttpContextScoped().Use(HttpContext.Current); при запуске приложения. Интересно, начнёт ли он работать, если вы удалите его?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...