Domanda

Ho bisogno di creare un ActionResult in un'applicazione ASP.NET MVC, che ha un tipo di file .csv.

Mi impegno a fornire un 'non chiamare' lista e-mail ai miei partner di marketing e voglio che ha un'estensione .csv nel tipo di file. Poi si aprirà automaticamente in Excel.

 http://www.example.com/mailinglist/donotemaillist.csv?password=12334

L'ho fatto con successo questo come segue, ma voglio per assicurarsi che questo è il modo migliore in assoluto e consigliato di fare questo.

    [ActionName("DoNotEmailList.csv")]
    public ContentResult DoNotEmailList(string username, string password)
    {
            return new ContentResult()
            {
                Content = Emails.Aggregate((a,b)=>a+Environment.NewLine + b), 
                ContentType = "text/csv"
            };
    }

Questa Actionmethod risponderà al link qui sopra bene.

Mi chiedo solo se non v'è un rischio di qualsiasi conflitto inaspettato di avere l'estensione del file in questo modo con qualsiasi versione diversa di IIS, qualsiasi tipo di filtro ISAPI, o qualsiasi altra cosa che posso pensare a ora.

ho bisogno di essere sicuro al 100% perché fornirà questo ai partner esterni e non voglio avere a cambiare la mia idea in seguito. Io davvero non vedo problemi, ma forse theres qualcosa di oscuro -. O di un altro più "MVC" come modo di fare questo

È stato utile?

Soluzione

Credo che la vostra risposta deve contenere "Content-Disposition" header in questo caso. Personalizza le tue ActionResult in questo modo:

public class MyCsvResult : ActionResult {

    public string Content {
        get;
        set;
    }

    public Encoding ContentEncoding {
        get;
        set;
    }

    public string Name {
        get;
        set;
    }

    public override void ExecuteResult(ControllerContext context) {
        if (context == null) {
            throw new ArgumentNullException("context");
        }

        HttpResponseBase response = context.HttpContext.Response;

        response.ContentType = "text/csv";

        if (ContentEncoding != null) {
            response.ContentEncoding = ContentEncoding;
        }

        var fileName = "file.csv";

        if(!String.IsNullOrEmpty(Name)) {
            fileName = Name.Contains('.') ? Name : Name + ".csv";
        }

        response.AddHeader("Content-Disposition",
            String.Format("attachment; filename={0}", fileName));

        if (Content != null) {
            response.Write(Content);
        }
    }
}

e utilizzarlo nella vostra azione, invece di ContentResult:

return new MyCsvResult {
    Content = Emails.Aggregate((a,b) => a + Environment.NewLine + b)
    /* Optional
     * , ContentEncoding = ""
     * , Name = "DoNotEmailList.csv"
     */
};

Altri suggerimenti

Ho usato l'azione FileContentResult di fare anche qualcosa di simile.

public FileContentResult DoNotEmailList(string username, string password)
{
        string csv = Emails.Aggregate((a,b)=>a+Environment.NewLine + b);
        byte[] csvBytes = ASCIIEncoding.ASCII.GetBytes( csv );
        return File(csvBytes, "text/csv", "DoNotEmailList.csv");
}

Si aggiungerà l'header Content-Disposition per voi.

Questo è il modo che sto facendo qualcosa di simile. Sto trattandolo come download:

var disposition = String.Format(
  "attachment;filename=\"{0}.csv\"", this.Model.Name);
Response.AddHeader("content-disposition", disposition);

Questo dovrebbe apparire nel browser come un file di download con il dato nome.

Non riesco a pensare a una ragione per cui il vostro non avrebbe funzionato, però.

La risposta è stata accettata è abbastanza buono, ma mantiene il contenuto dell'uscita in memoria come lo trasmette. Che cosa succede se il file che genera è piuttosto grande? Ad esempio, quando si dump di un contenuto della tabella SQL. L'applicazione potrebbe esaurire la memoria. Ciò che si desidera in questo caso è quello di utilizzare FileStreamResult. Un modo per alimentare i dati nel flusso potrebbe utilizzare tubo, come descritto qui

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top