前提・実現したいこと
学習用で簡易版のTwitterみたいなものを作ろうとしているところで、
現在、ファイルアップロード機能と、DBへの保存処理を実装中です。
表題のエラーが発生しており、色々とネットで調べたりしてるのですが、
エラーの種類が変わったりするものの、なかなか解決できず、質問させていただいております。
流れとしましては、
「新規投稿」画面(Create.vbhtml)で、
・投稿内容(Text)
・画像(ファイルアップロードにより)(Image)
・ユーザーID(今は手入力しますが、後に自動取得させる予定)(UserId)
をフォーム入力後、
「ツイートする」ボタン押下で、DBに保存し、投稿一覧画面にリダイレクトさせる想定です。
※提供情報に不足があれば、ご指摘いただけると助かります。
発生している問題・エラーメッセージ
コントローラーファイルの 「ph.Image = text ' データ本体」の行に、 「System.InvalidCastException」 のエラーが発生しております。 エラー文の中に文字化けのようなものも含まれておりますので、 添付画像で詳細をご確認お願いいたします。
該当のソースコード
※Viewファイル(Create.vbhtml)
※コードの途中にfontawesomeのアイコンが入っておりますが、将来的にアイコンクリックでファイルアップロード機能を持たせる予定で、
今はまだ使用しておりません。
VisualBasic
1@ModelType MyTwitter.MyTwitter.Tweet 2@Code 3 ViewData("Title") = "Create" 4End Code 5 6@Styles.Render("~/Content/Tweet/create.css") 7 8<h2>新規投稿</h2> 9 10@Using (Html.BeginForm("Create", "Tweets", FormMethod.Post, New With {.enctype = "multipart/form-data"})) 11 @Html.AntiForgeryToken() 12 13 @<div class="form-horizontal"> 14 <hr /> 15 @Html.ValidationSummary(True, "", New With {.class = "text-danger"}) 16 <div class="form-group"> 17 @Html.LabelFor(Function(model) model.Text, htmlAttributes:=New With {.class = "control-label col-md-2"}) 18 <div class="col-md-10"> 19 @Html.EditorFor(Function(model) model.Text, New With {.htmlAttributes = New With {.class = "form-control", .maxlength = "70", .rows = "4", .placeholder = "いまどうしてる?"}}) 20 @Html.ValidationMessageFor(Function(model) model.Text, "", New With {.class = "text-danger"}) 21 <div class="select-picture"> 22 <i class="far fa-images"></i> 23 @Html.HiddenFor(Function(model) model.Image, New With {.htmlAttributes = New With {.class = "form-control"}}) 24 </div> 25 </div> 26 </div> 27 28 <div Class="form-group"> 29 @Html.LabelFor(Function(model) model.UserId, htmlAttributes:=New With {.class = "control-label col-md-2"}) 30 <div class="col-md-10"> 31 @Html.EditorFor(Function(model) model.UserId, New With {.htmlAttributes = New With {.class = "form-control"}}) 32 @Html.ValidationMessageFor(Function(model) model.UserId, "", New With {.class = "text-danger"}) 33 </div> 34 </div> 35 36 <input type="file" name="fl" value="" /> 37 @ViewData("msg") 38 39 <div class="form-group"> 40 <div class="col-md-offset-2 col-md-10"> 41 <input type="submit" value="ツイートする" class="btn btn-default" /> 42 </div> 43 </div> 44</div> 45End Using 46 47<div> 48 @Html.ActionLink("ホームに戻る", "Index") 49</div>
※モデルファイル(Tweet.vb)
VisualBasic
1Imports System 2Imports System.ComponentModel 3Imports System.ComponentModel.DataAnnotations 4 5Namespace MyTwitter 6 7 Public Class Tweet 8 9 Public Property Id As Integer 10 11 <DisplayName("本文")> 12 <DataType(DataType.MultilineText)> 13 Public Property Text As String 14 15 Public Property Image As Byte 16 17 Public Property CreatedAt As DateTime 18 19 Public Property UpdatedAt As DateTime 20 21 Public Property UserId As Integer 22 23 End Class 24 25End Namespace
※コンテキストクラス(MyMvcContext.vb)
VisualBasic
1Imports System.Data.Entity 2Imports MyTwitter.MyTwitter 3 4Public Class MyMvcContext : Inherits DbContext 5 Public Property Tweets As DbSet(Of Tweet) ' Tweetsテーブル 6End Class
※コントローラ(TweetsController.vb)
VisualBasic
1Imports System 2Imports System.Collections.Generic 3Imports System.Data 4Imports System.Data.Entity 5Imports System.Linq 6Imports System.Net 7Imports System.Web 8Imports System.Web.Mvc 9Imports System.IO 10Imports MyTwitter.MyTwitter 11 12Namespace Controllers 13 Public Class TweetsController 14 Inherits System.Web.Mvc.Controller 15 16 Private db As New MyTwitterContext 17 18 ' GET: Tweets 19 Function Index() As ActionResult 20 Return View(db.Tweets.ToList()) 21 End Function 22 23 ' GET: Tweets/Create 24 Function Create() As ActionResult 25 Return View() 26 End Function 27 28 ' POST: Tweets/Create 29 '過多ポスティング攻撃を防止するには、バインド先とする特定のプロパティを有効にしてください。 30 '詳細については、https://go.microsoft.com/fwlink/?LinkId=317598 を参照してください。 31 <HttpPost()> 32 <ValidateAntiForgeryToken()> 33 Function Create(<Bind(Include:="Text,Image,CreatedAt,UpdatedAt,UserId")> ByVal tweet As Tweet, ByVal fl As HttpPostedFileBase) As ActionResult 34 35 ' コンテンツ・タイプが"image/*"であるか(画像ファイルか) 36 ' をチェック 37 If fl.ContentType.StartsWith("image/") Then 38 39 ' アップロード先のパスを生成 40 Dim upfile As String = Server.MapPath("~/App_Data/Photos/") & Path.GetFileName(fl.FileName) 41 42 ' 同名のファイルが存在する場合はエラー 43 If System.IO.File.Exists(upfile) Then 44 ViewData("msg") = "同名のファイルが存在します。" 45 Else 46 47 48 ' EDMのコンテキスト・オブジェクトを生成 49 'Dim _db As New MyMvcEntities() 50 Dim _db As New MyMvcContext() 51 52 ' エンティティにアップロード・ファイルの情報をセット 53 Dim ph As New Tweet() 54 'ph.Name = Path.GetFileName(fl.FileName) ' ファイル名 55 'ph.Mime = fl.ContentType ' コンテンツ・タイプ 56 57 Dim data(fl.ContentLength) As Byte 58 fl.InputStream.Read(data, 0, fl.ContentLength) 59 'Dim text As String = data.ToString 60 Dim text As String = System.Text.Encoding.UTF8.GetString(data) 61 ph.Image = text ' データ本体 62 63 ' エンティティを追加&データソースに反映 64 _db.Tweets.Add(ph) 65 _db.SaveChanges() 66 67 68 69 ' 画像ファイルで同名のファイルが存在しない場合は保存処理 70 'fl.SaveAs(upfile) 71 ViewData("msg") = String.Format("{0}をアップロードしました。", fl.FileName) 72 73 74 End If 75 Else 76 ' 画像ファイルでない場合はエラー 77 ViewData("msg") = "画像以外はアップロードできません。" 78 End If 79 80 81 If ModelState.IsValid Then 82 db.Tweets.Add(New Tweet With { 83 .Text = tweet.Text, 84 .CreatedAt = DateTime.Now, 85 .UpdatedAt = DateTime.Now, 86 .UserId = tweet.UserId 87 }) 88 89 db.SaveChanges() 90 91 92 ' 入力元のフォームに結果を表示 93 Return RedirectToAction("Index") 94 Else 95 Return View(tweet) 96 End If 97 98 End Function 99 100 End Class 101End Namespace
試したこと
以下の記事を参考にしました。
ファイルアップロード、およびデータベースへの保存機能につきましては、以下の2つを参考にしました。
■ファイルアップロード
https://www.atmarkit.co.jp/fdotnet/dotnettips/935aspmvcfileupload1/aspmvcfileupload1.html
■データベースへの保存
https://www.atmarkit.co.jp/fdotnet/dotnettips/939aspmvcfileupload2/aspmvcfileupload2.html
補足情報(FW/ツールのバージョンなど)
統合開発環境
Visual Studio2019
(言語:VB.NET、プロジェクトテンプレート:ASP.NET Webアプリケーション MVC)
MVCフレームワークのバージョン
5.2.7
使用PC
Windows10
※平日は仕事のため、返信が19:30以降になります。
※休日の返信は不定期です。
申し訳ございませんが、どうぞよろしくお願いします。
回答1件
あなたの回答
tips
プレビュー