ASP.Net MVC et de l'état - comment garder de l'état entre les demandes

Comme un assez expérimenté ASP.Net développeur tout récemment de commencer à utiliser MVC, je me retrouve un peu en difficulté à changer mon état d'esprit à partir d'un traditionnel ", le serveur de contrôle et de gestionnaire d'événement" façon de faire les choses, dans la plus dynamique MVC sorte de choses. Je pense que je suis en train d'en arriver là, mais parfois, le MVC "magique" me jette hors.

Mon scénario actuel est de créer une page web qui permet à l'utilisateur de parcourir un fichier local, de le télécharger sur le serveur et répétez cette opération jusqu'à ce qu'il y a une liste de fichiers pour travailler avec. Quand il est heureux avec la liste des fichiers (qui sera affiché dans une grille sur la page), il va cliquer sur un bouton pour traiter les fichiers et d'en extraire certaines données qui seront stockées dans une base de données.

La dernière partie n'est pas si important, en ce moment je suis aux prises avec quelque chose d'aussi trivial que la constitution d'une liste de fichiers, et la persistance de cette liste entre les demandes. Dans l'approche traditionnelle, ce serait extrêmement simple - les données devraient être conservées dans l'état d'affichage. Mais dans MVC-je besoin pour transmettre les données entre le contrôleur et la vue, et je ne suis pas entièrement comment c'est censé fonctionner.

Je suppose que je ferais mieux de poster mon incomplètes tentative de codage pour expliquer le problème.

Afin de conserver ma liste de fichiers de données, j'ai créé un viewmodel qui est en fait une liste tapée de fichiers, ainsi que certains de métadonnées supplémentaires:

public class ImportDataViewModel
{
    public ImportDataViewModel()
    {
        Files = new List<ImportDataFile>();
    }

    public List<ImportDataFile> Files { get; set; }
...

Dans la vue, j'ai un formulaire pour la navigation et de téléchargement du fichier:

<form action="AddImportFile" method="post" enctype="multipart/form-data">
  <label for="file">
    Filename:</label>
  <input type="file" name="file" id="file" />
  <input type="submit" />
  </form>

La vue est à l'aide de ce dernier comme son modèle:

@model MHP.ViewModels.ImportDataViewModel

Cela permettra d'envoyer le fichier à mon action:

public ActionResult AddImportFile(HttpPostedFileBase file, ImportDataViewModel importData)
    {

        if (file.ContentLength > 0)
        {
            ImportDataFile idFile = new ImportDataFile { File = file };
            importData.Files.Add(idFile);
        }

        return View("DataImport", importData);
    }

Cette action revient à l'affichage de la DataImport page, ainsi que le viewmodel instance contenant la liste des fichiers.

Cela fonctionne très bien jusqu'à un certain point, je peux parcourir un fichier et le télécharger, et je peux voir le viewmodel de données à l'intérieur de l'action, et puis aussi si j'ai mis un point d'arrêt à l'intérieur de la vue et de débogage "ce.Modèle", tout va bien.

Mais alors, si j'essaie de télécharger un autre fichier, lorsque vous mettez un point d'arrêt à l'intérieur de la AddImportFile action, le importData paramètre est vide. Donc, la vue n'est évidemment pas de passage à l'instance actuelle de son modèle à l'action.

Dans le MVC échantillons que j'ai traversé, l'instance du modèle est "comme par magie" passé à la méthode d'action en tant que paramètre, alors pourquoi est-il vide?

Je suppose que le vrai problème, c'est ma compréhension limitée de la MVC, et qu'il y a probablement une solution très simple à ce. De toute façon, je vous serais extrêmement reconnaissant si quelqu'un pouvait me diriger dans la bonne direction.

  • Vous n'êtes pas stocker les fichiers téléchargés n'importe où sur le serveur. Comment voulez-vous que ils afin de être a persisté entre les publications? Tout ce que vous avez à l'intérieur de votre <form> est un fichier unique champ de saisie. Donc tout ce que vous pouvez vous attendre à obtenir dans l'action du controller est ce fichier. Rien de plus. Il n'y a pas de magie. Il n'y a pas d'état d'affichage dans ASP.NET MVC.
  • Darin, merci pour votre commentaire. Il est vrai que je ne suis pas stocker le fichier sur le serveur. Je pourrais stocker dans la base de données, mais ce serait un gaspillage de l'espace de base de données et l'utilisateur de la patience, car il faudrait beaucoup de temps et il n'y a pas de réel besoin d'elle. Ce que j'aimerais faire, c'est juste pour le garder dans la mémoire du serveur en tant que variable d'une certaine manière jusqu'à ce que l'utilisateur décide de le traiter. Alors je vais stocker le résultat de ce traitement à la base de données. Je pense que soit je suis en train d'utiliser MVC dans le mauvais sens, ou je ne sais juste pas comment le faire. Je ne sais pas de laquelle il s'est encore...
  • En gardant les fichiers dans la mémoire du serveur est l'une des pires choses. Éviter à tout prix. Non seulement que cela consomme beaucoup de mémoire sur le serveur, mais n'oubliez pas que IIS pourrait recycler le domaine d'application à tout moment, de perdre toutes les données stockées dans la mémoire. Aussi de ce que si vous exécutez dans une batterie de serveurs? Si vous enregistrez dans la mémoire du serveur, cela signifie que seulement 1 serveur de la ferme dispose de cette information et si l'équilibrage de charge distribue les requêtes suivantes sur un autre serveur de la batterie de serveurs, vous perdez l'information.
  • Ok, donc ce que suggérez-vous alors? Pour tout stocker dans la base de données n'importe quoi? En général, pour stocker les fichiers dans la mémoire est généralement une mauvaise idée, mais si vous savez que les fichiers sont petits, peu, et seulement une ou quelques utilisateurs le téléchargement en même temps, je pense qu'il peut être justifiée. Mais nous allons plutôt que de généraliser la discussion un peu - au lieu de fichiers, pensez par exemple un panier contenant une petite quantité de données. Encore s'agit-il de mal à utiliser une sorte de mécanisme de session comme un stockage intermédiaire dans MVC? Quelle est l'alternative?
  • Je sais que c'est vieux maintenant, mais je suis juste curieux de savoir pourquoi ne pas envisager l'option de la juste temporairement écrire le fichier dans un dossier, puis la nettoyer? Je l'ai fait un certain nombre de fois avec beaucoup de succès au fil des ans.
  • C'est drôle de lire ces "vieilles" questions, et de penser à combien le monde a changé en seulement cinq ans! Depuis, j'ai traitées avec upload de fichier, de nombreuses fois, et maintenant j'ai tendance à penser très différemment à ce sujet que de revenir ensuite. Je suis d'accord avec Steves suggestion que stocker le fichier temporairement est probablement la meilleure option, même si j'ai tendance à utiliser Azure blob storage plutôt qu'un dossier sur le serveur web. Zut, je n'ai pas utiliser IIS plus, c'est tout simplement Azure web apps ou Azure fonctions.
  • Je prends aussi mes demandes précédentes sur le stockage des trucs dans la mémoire, j'ai failli ne peut pas croire que j'ai réellement pensé que c'était une bonne idée! 🙂 Je suppose que, pour ma défense, que l'application en question était une petite enterprise application avec peu d'utilisateurs et de petits fichiers, mais néanmoins, je ne pense jamais à le faire aujourd'hui! Je suppose que nous devrions tous être reconnaissants pour la capacité de regarder en arrière à horribles erreurs du passé et de conclure que nous avons beaucoup développé depuis 🙂 cheers!

InformationsquelleAutor TMan | 2012-05-25