iT邦幫忙

0

ASP.NET MVC匯出Excel錯誤

請教各位先進,我寫一個Excel匯出功能,在VS下執行的環境下是可以正常匯出Excel的
但將程式碼更新至線上的IIS運作,執行同樣的匯出功能卻直接報500(Internal Server Error),想用try catch截取錯誤訊息也截取不到,不知道先進們是否知道該如何處理此狀況呢?
try catch抓錯誤訊息都抓不到,我真不知道該怎麼找問題了,在VS下的localhost運作都是正常的,程式也沒什麼複雜的東西,但遇到這樣的錯誤還真不知道怎麼解決~
是IIS上少安裝了什麼Excel的組件嗎?還是說IIS要設定什麼才可執行?
目前這台Web Server同時也有跑其它網站是Web From,而這網站也有寫Excel匯出功能,是可正常匯出的,當然寫法跟MVC不同,不知是否是MVC的寫法問題出錯~

public ActionResult ExportPapersExcel(int ConferenceId)
{
    var exportSpource = GetExportDataWithAllColumns(ConferenceId);
    var dt = JsonConvert.DeserializeObject<DataTable>(exportSpource.ToString());
    string ConferenceTitle = conferenceSrv.GetConferenceTitle(ConferenceId);
    try
    {
        return new ExportExcelResult
        {
            SheetName = "List",
            FileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".xlsx",
            ExportData = dt
        };
    }
    catch (Exception e)
    {
        publicSrv.AddLog(Session["MemberId"].ToString(), "ExportPapersExcel", "匯出Excel錯誤:" + e.ToString(), 0, 0);
        throw;
    }

}
public JArray GetExportDataWithAllColumns(int ConferenceId)
{
    var query = paperSrv.GetExcelPaperList(ConferenceId);
    JArray jObjects = new JArray();
    foreach (var item in query)
    {
        var jo = new JObject
        {
            {"稿件編號", item.CleanTitle},
            {"論文標題", item.Title},
            {"投稿類別", item.TrackTitle},
            {"投稿者", item.MemberName},
            {"新增作者", item.AuthorsName},
            {"關鍵字", item.Keyword},
            {"論文發表方式", item.Award},
            {"是否參選優秀論文評選", item.PresentationName},
            {"稿件狀態", item.StatusName},
            {"提交日期", item.SubmittedDate}
        };
        jObjects.Add(jo);
    }
    return jObjects;
}
看更多先前的討論...收起先前的討論...
w4560000 iT邦新手 4 級 ‧ 2020-06-30 12:14:44 檢舉
埋log在catch看一下
leo226 iT邦新手 5 級 ‧ 2020-06-30 15:39:15 檢舉
有埋了,系統直接報錯,沒有跳進catch裡~
w4560000 iT邦新手 4 級 ‧ 2020-06-30 17:36:04 檢舉
try的範圍不夠大 那就再大一點XD
leo226 iT邦新手 5 級 ‧ 2020-06-30 18:19:46 檢舉
己經整個code都全包了,極限了
player iT邦大師 1 級 ‧ 2020-06-30 23:30:57 檢舉
你要不要在ASP.NET MVC用Elmah.MVC這個套件看看
能不能接到錯誤訊息?
leo226 iT邦新手 5 級 ‧ 2020-07-01 11:50:55 檢舉
感謝各方先進提供建議,問題己找到~
原因是因為我沒有把匯出Excel套件.dll檔丟上去IIS的專案裡,所以直接報錯無法執行~
我上IIS的方式是將local端的整包專案,複制到IIS上(除了Controller和Model),所以每次修改程式後,只會更新View和編譯後的.dll檔到bin資料夾。
我原本以為編譯後的.dll檔會一併的把Nuget下載下來的套件一起編輯進去,原來不會~原來下載下來的套件.dll需要一併手動把它丟到IIS上才可正常運作。
另外想請問上IIS的方式好像還有用發佈的形式來更新,但整個資料架構好像都會被重整,不知道這兩種上線的方式有什麼差異呢?
w4560000 iT邦新手 4 級 ‧ 2020-07-01 12:22:08 檢舉
你是指發行嗎?
發行後生成的資料夾不會有cs檔,只有dll檔和一些靜態檔案,你就不用管要排除Controller和Model的檔案,但有第三方套件的話你也還是要把第三方套件dll加進去,不然就整個bin都搬過去
0
浩瀚星空
iT邦超人 1 級 ‧ 2020-06-30 10:47:55

從程式碼比較難看出問題。
正常最好是從錯誤訊息來查看。

不過你說沒辦法知道錯誤訊息。就比較難了解發生什麼事。

基本上我會先猜測看看是不是路徑或是權限的問題。
可以先試著把你的站改成debug模式。搞不好就能輸出錯誤了。

leo226 iT邦新手 5 級 ‧ 2020-06-30 11:06:22 檢舉

我看debug模式是開啓的也,直接報500錯誤就沒辦法抓真正的錯誤訊息了~
資料來源是DB,下載的路徑是瀏覽器預設的下載位置~~
資料來源與下載位置看似好像不會有什麼權限的問題~

<compilation debug="true" targetFramework="4.5.2" />

那就只好從log中查看了。
基本上生成檔案有時是需要一個暫存的地方。
等生成好了才會去觸發下載的動作。
比較常犯的錯誤,就是暫存檔的路徑位置錯了或是權限沒開。

可以的話從log查看,如果沒log的話。就先打開log記錄。
這樣才好知道實際問題。要不然這樣猜也不是辦法。

leo226 iT邦新手 5 級 ‧ 2020-07-01 11:52:19 檢舉

感謝各方先進提供建議,問題己找到~如上所述~謝謝~

0
Billour
iT邦新手 5 級 ‧ 2020-06-30 13:15:01

你好,依照這個問題,我會先一步步 Debug.

以下是我的做法

  1. 在每個重要地方,放上 Response.Write(obj);
  2. 執行,看程式死在那裡。

通常就會找出原因來了。

public ActionResult ExportPapersExcel(int ConferenceId)
{
    var exportSpource = GetExportDataWithAllColumns(ConferenceId);
    var dt = JsonConvert.DeserializeObject<DataTable>(exportSpource.ToString());
    Response.Write("A1"); /* 這裡*/
    string ConferenceTitle = conferenceSrv.GetConferenceTitle(ConferenceId);
    try
    {
    Response.Write("A2"); /* 這裡*/
        return new ExportExcelResult
        {
        Response.Write("A3"); /* 這裡*/
            SheetName = "List",
            FileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".xlsx",
            ExportData = dt
            Response.Write("A4"); /* 這裡*/
        };
    }
    catch (Exception e)
    {
    Response.Write("E1"); /* 這裡*/
        publicSrv.AddLog(Session["MemberId"].ToString(), "ExportPapersExcel", "匯出Excel錯誤:" + e.ToString(), 0, 0);
        throw;
    }

}
public JArray GetExportDataWithAllColumns(int ConferenceId)
{
Response.Write("C1"); /* 這裡*/
    var query = paperSrv.GetExcelPaperList(ConferenceId);
    Response.Write("C2"); /* 這裡*/
    JArray jObjects = new JArray();
    foreach (var item in query)
    {
    Response.Write("D1"); /* 這裡*/
        var jo = new JObject
        {
        Response.Write("D2"); /* 這裡*/
            {"稿件編號", item.CleanTitle},
            {"論文標題", item.Title},
            {"投稿類別", item.TrackTitle},
            {"投稿者", item.MemberName},
            {"新增作者", item.AuthorsName},
            {"關鍵字", item.Keyword},
            {"論文發表方式", item.Award},
            {"是否參選優秀論文評選", item.PresentationName},
            {"稿件狀態", item.StatusName},
            {"提交日期", item.SubmittedDate}
        };
        jObjects.Add(jo);
        Response.Write("D3"); /* 這裡*/
    }
    return jObjects;
}
看更多先前的回應...收起先前的回應...
leo226 iT邦新手 5 級 ‧ 2020-06-30 14:24:33 檢舉

依大大的方法,把每個地方都加入log:
因為是匯出功能,所以Response.Write("");好像無法有效果
我有自己寫記錄在DB的log,如下程式碼是有記錄到A2的階段都沒問題,所以發生錯誤的地方應該是在最後的
return new ExportExcelResult這個地方,但還是不知道為何在VS 的localhost可以正常執行,在IIS上就直接死掉,500錯誤!!!

ExportPapersExcel?ConferenceId=1012 500 (Internal Server Error)
public ActionResult ExportPapersExcel(int ConferenceId)
{
    var exportSpource = GetExportDataWithAllColumns(ConferenceId);
    var dt = JsonConvert.DeserializeObject<DataTable>(exportSpource.ToString());
    publicSrv.AddLog(Session["MemberId"].ToString(), "ExportPapersExcel", "匯出Excel錯誤:A1", 0, 0);
    Response.Write("A1");
    try
    {
        Response.Write("A2");
        publicSrv.AddLog(Session["MemberId"].ToString(), "ExportPapersExcel", "匯出Excel錯誤:A2", 0, 0);
        return new ExportExcelResult
        {
            SheetName = "稿件清單",
            FileName = "exportList.xlsx",
            ExportData = dt
        };
    }
    catch (Exception e)
    {
        Response.Write("A3");
        publicSrv.AddLog(Session["MemberId"].ToString(), "ExportPapersExcel", "匯出Excel錯誤:" + e.ToString(), 0, 0);
        throw;
    }
}
leo226 iT邦新手 5 級 ‧ 2020-06-30 15:38:37 檢舉

我改用別的套件EEPLus,測試匯出的情況還是一樣,在IIS上運作就直接報錯,但在VS的環境下卻可以正常運作,實在是搞不懂問題出在那裡~

//EEPLus
public ActionResult Export(int ConferenceId)
{
    //取出要匯出Excel的資料
    var query = paperSrv.GetExcelPaperList(ConferenceId);
    //建立Excel
    ExcelPackage ep = new ExcelPackage();
    //建立第一個Sheet,後方為定義Sheet的名稱
    ExcelWorksheet sheet = ep.Workbook.Worksheets.Add("FirstSheet");
    int col = 1;    //欄:直的,因為要從第1欄開始,所以初始為1
    //第1列是標題列 
    //標題列部分,是取得DataAnnotations中的DisplayName,這樣比較一致,
    //這也可避免後期有修改欄位名稱需求,但匯出excel標題忘了改的問題發生。
    //取得做法可參考最後的參考連結。
    sheet.Cells[1, col++].Value = "PaperId";
    //資料從第2列開始
    int row = 2;    //列:橫的
    foreach (PaperViewModel item in query)
    {
        col = 1;//每換一列,欄位要從1開始
                //指定Sheet的欄與列(欄名列號ex.A1,B20,在這邊都是用數字),將資料寫入
        sheet.Cells[row, col++].Value = item.PaperId;
        row++;
    }
    //因為ep.Stream是加密過的串流,故要透過SaveAs將資料寫到MemoryStream,在將MemoryStream使用FileStreamResult回傳到前端
    MemoryStream fileStream = new MemoryStream();
    ep.SaveAs(fileStream);
    ep.Dispose();//如果這邊不下Dispose,建議此ep要用using包起來,但是要記得先將資料寫進MemoryStream在Dispose。
    fileStream.Position = 0;//不重新將位置設為0,excel開啟後會出現錯誤
    return File(fileStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "ExportRanger.xlsx");
}
Billour iT邦新手 5 級 ‧ 2020-06-30 15:52:09 檢舉

你好,也有可能是 IIS 的設定問題,
請試看看:

iis 檔案權限 寫入
  1. IIS7設定站台資料夾的”寫入”權限:

如果站台有”特別指定應用程式集區”,
則網站資料夾的安全性要指定 “IIS AppPool\站台的應用程式集區” 可以寫入

如果站台沒有指定,是用預設的DefaultAppPool
則網站資料夾的安全性要指定 “IIS_IUSRS” 可以寫入
(因為IIS_IUSRS群組已經包括DefaultAppPool帳戶)

網址: http://blog.fhps.tp.edu.tw/fhpsmis/?p=1023

設定IIS權限

leo226 iT邦新手 5 級 ‧ 2020-07-01 11:52:26 檢舉

感謝各方先進提供建議,問題己找到~如上所述~謝謝~

Billour iT邦新手 5 級 ‧ 2020-07-01 14:20:47 檢舉

麻煩你給出最佳答案吧。

0
w4560000
iT邦新手 4 級 ‧ 2020-06-30 18:38:21

不然找看看事件檢視器 有沒有錯誤訊息

類似這樣
https://ithelp.ithome.com.tw/upload/images/20200630/20110125jwyivE0w0M.png
https://ithelp.ithome.com.tw/upload/images/20200630/20110125A3BYTBk7EY.png

leo226 iT邦新手 5 級 ‧ 2020-07-01 11:52:30 檢舉

感謝各方先進提供建議,問題己找到~如上所述~謝謝~

我要發表回答

立即登入回答