- PR -

[ASP.NET] MapPathでパスを取得できない

投稿者投稿内容
ぐう
会議室デビュー日: 2003/10/08
投稿数: 4
お住まい・勤務地: 滋賀
投稿日時: 2004-03-15 20:49
はじめまして。
いつもありがたく利用させて頂いています。

現在、VB.NETを使用してWEBアプリケーションを作成しています。
メッセージファイルを読むために、以下のようなモジュールを作成したのですが、

****コードここから****
Module KIMJ0010
Private page As New System.Web.UI.Page
Private fname As String
Function Meseg(ByVal msgno As Integer)
fname = page.Server.MapPath("\Application\MsegeFile.txt")
Try
FileOpen(1, fname, OpenMode.Input, _
OpenAccess.Read, OpenShare.LockWrite)
    :
Catch ex As Exception
Return "メッセージファイルの取得に失敗しました。"
Finally
FileClose(cnt)
End Try

End Function
End Module
****コードここまで****

上記にようにして実行したところ、正常にファイルを読んでいるのですが、
何度か実行していると下記のエラーが出て、それ以降は同じエラーが出ます。

****エラーここから****

パス '/Application/MsegeFile.txt' を割り当てられませんでした。
説明 : 現在の Web 要求を実行中に、ハンドルされていない例外が発生しました。エラーに関する詳細および例外の発生場所については、スタック トレースを参照してください。
例外の詳細: System.Web.HttpException: パス '/Application/MsegeFile.txt' を割り当てられませんでした。
ソース エラー:
行 39: fname = page.Server.MapPath("\Application\MsegeFile.txt")  '(赤色の行)

****エラーここまで****

MapPath の処理でパスの取得が出来ていない というのは判断できるのですが、
「最初は取得できている」ので、何が原因なのかわからない状態です。

このような現象を経験された方はいらっしゃるでしょうか?
また、この現象を回避する方法があればご教示頂けないでしょうか。


[ メッセージ編集済み 編集者: ぐう 編集日時 2004-03-15 20:49 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-03-16 09:21
引用:

ぐうさんの書き込み (2004-03-15 20:49) より:

Module KIMJ0010 ←これと、
Private page As New System.Web.UI.Page ←これ
Private fname As String
Function Meseg(ByVal msgno As Integer)
fname = page.Server.MapPath("ApplicationMsegeFile.txt")
End Module


 引用の太字で示した行がとても気になったのですが。。。

 ここでmoduleにされているのは「他でも使うから」だと思いますが、それであるなら、publicなclassでもいけます。ASP.NETでmoduleは、VB6.0の頃のmoduleと、少し違う動きをするらしい(弱気)ので、使わないのがベターです。

 そして、このモジュール関数の呼び出し元が、おそらく例外に関係していると思います。ここでNewしているPageは、MapPathを使うためのものですよね?これはおそらくMapPathがインスタンスメソッドとして用意されているから、このようにされたのだと思いますが、ここでちょっと考えてください。
 なぜ、クラスメソッドでなく、インスタンスメソッドなのか。
.NET Frameworkの他のメソッドには、たくさんのクラスメソッド、インスタンスがなくても使える、sharedで宣言されているメソッドがあります。なのに、なぜ、インスタンスメソッドなのか。これは、インスタンス化して、何らかの情報がなければ使えないことを意味しています。おそらく、アセンブリか、アプリケーションドメインが関係していると思います。例外が発生するのは、そういう情報がないから、と想像されます。


 こんな風にできませんかね?

Public Class KIMJ0010
 Public Shared Function GetMessage(ByVal msgno As Integer, _
 <Description("呼び出し元ページ")> ByVal ParentPage As System.Web.UI.Page) _
 As String
  Dim fname As String = ParentPage.Server.MapPath("〜")
  (以下略)
 End Function
End Class
ぢゃん♪
大ベテラン
会議室デビュー日: 2003/06/12
投稿数: 208
お住まい・勤務地: 都内
投稿日時: 2004-03-16 09:30
System.Web.UI.Page クラスのインスタンスがないならば、
コード:
fname = page.Server.MapPath("\Application\MsegeFile.txt")


とわざわざ System.Web.UI.Page を経由しなくとも、HttpServerUtility.MapPath メソッドのヘルプにもあるとおり
引用:

HttpServerUtility.MapPath メソッドより:

指定した Web サイトを格納する仮想ディレクトリの物理パスを返す例を次に示します。分離コード モジュールで MapPath を読み取るには、 HttpContext.Current.Server.MapPath を使用します。


で十分かと。

気になるのは結果的にSharedなメソッドであることですが。このメソッドを処理中に、別セッションがこのメソッドを実行しようとしたら、どうなるでしょうね。未確認ですが。

[ メッセージ編集済み 編集者: ぢゃん♪ 編集日時 2004-03-16 09:42 ]
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-03-16 10:37
引用:

ぢゃん♪さんの書き込み (2004-03-16 09:30) より:
引用:

HttpContext.Current.Server.MapPath を使用します。


で十分かと。


これは仰るとおり、というかこれで正解だと思うのですが、
引用:

気になるのは結果的にSharedなメソッドであることですが。このメソッドを処理中に、別セッションがこのメソッドを実行しようとしたら、どうなるでしょうね。未確認ですが。


これ、どういう意味でしょう?(結果的にSharedなメソッドとは?)
ぐう
会議室デビュー日: 2003/10/08
投稿数: 4
お住まい・勤務地: 滋賀
投稿日時: 2004-03-16 10:39
Jitta様 ぢゃん♪様 ありがとうございます。

引用:

Jittaさんの書き込み (2004-03-16 09:21) より:
 ここでmoduleにされているのは「他でも使うから」だと思いますが、それであるなら、publicなclassでもいけます。ASP.NETでmoduleは、VB6.0の頃のmoduleと、少し違う動きをするらしい(弱気)ので、使わないのがベターです。


ここでmoduleにした理由は、Jitta様が仰られた通り、「他フォームでの使用」「フォーム内の各所での使用」を目的としています。
classにしなかったのは、毎回classの宣言をするのが面倒だったという理由です・・(反省

まずは、Jitta様に挙げて頂いた方法で試してみようと思います。

引用:

ぢゃん♪さんの書き込み (2004-03-16 09:30) より:
気になるのは結果的にSharedなメソッドであることですが。このメソッドを処理中に、別セッションがこのメソッドを実行しようとしたら、どうなるでしょうね。未確認ですが。



ぢゃん♪様の気になっておられる所は

FileOpen(1, fname, OpenMode.Input, OpenAccess.Read, OpenShare.LockWrite)

この部分でしょうか? 
現在ファイルポインタの番号を現在1で固定しているのですが、ここを変数にして実行のたびに別番号で開いていけば、ポインタは重複しないかな・・と考えていたりします。
 

#なぜか家から見ようと思ったら@ITトップページが開かなくて困りまくりでした。(汗
ぢゃん♪
大ベテラン
会議室デビュー日: 2003/06/12
投稿数: 208
お住まい・勤務地: 都内
投稿日時: 2004-03-16 10:56
引用:

なちゃさんの書き込み (2004-03-16 10:37) より:
引用:

気になるのは結果的にSharedなメソッドであることですが。このメソッドを処理中に、別セッションがこのメソッドを実行しようとしたら、どうなるでしょうね。未確認ですが。


これ、どういう意味でしょう?(結果的にSharedなメソッドとは?)


ここ↓です。Moduleに「インスタンス」の概念はないはずですから、あくまでも結果的にですが、Sharedなメソッドと言えるでしょう。
コード:

Module KIMJ0010



引用:

ぐうさんの書き込み (2004-03-16 10:39) より:

FileOpen(1, fname, OpenMode.Input, OpenAccess.Read, OpenShare.LockWrite)

この部分でしょうか? 
現在ファイルポインタの番号を現在1で固定しているのですが、ここを変数にして実行のたびに別番号で開いていけば、ポインタは重複しないかな・・と考えていたりします。


それもありますし、そのアクセス中にServer.MapPathで同じパスを問い合わせたらどうなるか……とか(←未確認なのでなんとも言えませんけど)。

要するに、

  • メンバ変数使用の競合がないか
  • (上と関連しますが)メソッド自体に排他をかけなくてもOKなのかどうか
ということです。
(↑排他の件は「メソッド自体に排他をかけてください」という強制的な意味ではありません。)

[ メッセージ編集済み 編集者: ぢゃん♪ 編集日時 2004-03-16 11:08 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-03-16 11:04
引用:

ぐうさんの書き込み (2004-03-16 10:39) より:

classにしなかったのは、毎回classの宣言をするのが面倒だったという理由です・・(反省


 とりあえず、、、あまり薦められることではありませんが、Shared宣言をすると、クラスの宣言はしなくてもいいです。

Public Class xxx
 Public Shared Sub X1()
 End Sub
 Public Sub X2()
 End Sub
End Class

X1は、xxx.X1()と使用できる。
X2は、インスタンスを作らなければならない。
Dim x2 As New xxx()
x2.X2()


 ところで、「なぜ失敗したか」は確実に突き止めておいた方がよいと思います(というか、私がその理由を知りたい、のだが)。ぢゃん♪さんの方法のように、

Public Class KIMJ0010
 Public Shared Function GetMessage(ByVal msgno As Integer) As String
  Dim fname As String = HttpContext.Current.Server.MapPath("〜")
  (以下略)
 End Function
End Class

とする方がよいのですが、、、私が気になるのはPageを呼び出しごとにNewしていたために発生した例外なのか、呼び出し元のコンテキストがとれずに発生した例外なのか、というところです。ここは切り分けなければならないと思います。
#後々同じような現象が発生したときの、解決の助けにもなります
ぐう
会議室デビュー日: 2003/10/08
投稿数: 4
お住まい・勤務地: 滋賀
投稿日時: 2004-03-16 11:26
皆様 ご意見ありがとうございます。

近くの人にも聞いてみたのですが、
その方は「ファイル名が長い」と仰られました。
MsegeFile が9文字で、それに原因があるのでは?
との事でした。
(エラーの詳細までは見ておられません)

しばらくは読めていたという点からすると、直接的な原因ではないような気がしますが、これについても併せて確認してみたいと思います。
エラーが出るタイミングがはっきりしないので、どの状態がダメなのか確認は難しいですが、出来る限り原因の追求を行いたいと思います。


スキルアップ/キャリアアップ(JOB@IT)