読者です 読者をやめる 読者になる 読者になる

BEACHSIDE BLOG

MicrosoftとかC#を好むレンジャーの個人的メモ

page_load時にfromタグのactionを変更(VB、WebForms)

久々にVBとWebFormsをいじる用事があったので書き留めました。

ページをロードするときに、formのactionを書き換えようって話です。
環境は
VS2013、.net framework4.5
VBASP.NET WebForms
です。

方法としては、

  • Page_Loadの動作時に、なんらかの条件をもとに、指定のformのactionを書き換える。
  • jsonで、キーとなる値とそのactionとなる値を持っておき、キーが条件とマッチするactionに書き換える。

って感じです。

jsonさんは、簡易なリストを作って、プロジェクトの直下においておきました。

[
    { "Ip": "ip1", "Action": "http://www.msn.com/ja-jp" },
    { "Ip": "ip2", "Action": "http://www.yahoo.co.jp/" },
    { "Ip": "ip3", "Action": "http://www.microsoftvirtualacademy.com/" }
]

適当なWebページ(今回は、DynamicAction.aspxとします)というWebページをプロジェクト直下に追加します。
そのページにデフォルトで生成されたformタグにsubmitするボタンつけただけです。コードビハインドでタグのidを呼べるようにするには、タグのattributeに「runat="server"」つけておくのはポイントです。(今回のサンプルはデフォルトでついてますけど...)

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="DynamicAction.aspx.vb" Inherits="VB_webforms_demo01.DynamicAction" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" action="http://www.asp.net/" runat="server">
        <div>
        </div>
        <input type="submit" value="submit" />
    </form>
</body>
</html>


Jsonの処理は、みんな大好きJson.NETを使います。Nugetからインストールしておきます。

JsonのDeserializeしたものを格納するのに、ActionMapというクラスを用意しました。
条件とマッチングさせるキーとなるプロパティを「Ip」、actionは「Action」プロパティを用意しました。
実際に格納するのは、ActionMapのListにします。

Class ActionMap
    Public Property Ip As String
    Public Property Action As String
End Class

今回は、
ActionMapのクラスも、Jsonを処理するメソッドも、Webページのコードビハインド、DynamicAction.aspx.vbに書いちゃいました。
Jsonの処理なんて、多少真面目に書くときは、Helperみたなクラス作ってpublicでstaticな(あ、VBだとSharedか)のにすべきですかね。
で、Genericsで...とかでしょうね。

ということで、DynamicAction.aspx.vbには、まずnamespaceをインポートしておきます。

Imports Newtonsoft.Json
Imports System.IO

Jsonファイルから値取得して、ActionMapのListにする処理のメソッドをこんな感じで...。

    Private Sub CreateActionMapListFromJson()
        Using reader As New StreamReader(Server.MapPath("actionMap.json"))
            Dim serializer = New JsonSerializer
            actionMapList = serializer.Deserialize(reader, GetType(List(Of ActionMap)))
        End Using
    End Sub

serializer.Deserializeの戻り値になるactionMapList は、DynamicAction.aspx.vbのメンバー変数として宣言してます(諸事情により)。

Private actionMapList As List(Of ActionMap)

C#で書いてるときは、json.netのサンプルの通りにserialize.Deserializeのときに明示的にキャストしてるんですが、今回のサンプルでは、...(ry
必要あるのかなーとか内心思ってますが、なーんも考えてません...
余談ですが、久々にVBやると、C#のtypeofのノリでVBでもtypeof使ったら怒られて、なんか笑えました...
VBだと、GetTypeですね。

さて、本題のPage_Loadの処理です。

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        CreateActionMapListFromJson()
        '今回はとりあえず、こんな条件
        Dim targetIp = Request.Url.ToString
        Dim action = actionMapList.
                        Where(Function(n) n.Ip = targetIp).
                        Select(Function(n) n.Action).
                        FirstOrDefault
        If (Not IsNothing(action)) Then form1.Action = action
    End Sub

Jsonの処理メソッドを呼んで、Jsonファイルから取得した値をActionMapのListをメンバー変数に入れます。
とある指定の条件(変数:targetIp)が、ListのActionMapクラスのIpプロパティとイコールだったら、そのActionプロパティを取得するという処理にしています。
とある指定の条件は適当につくりました(諸事情によりこれ)。

条件とマッチしたものがあれば、取得したActionプロパティの値をform1のactionの値として書き換えます。マッチするのがなければ、aspxに書いたactionをそのまま実行です。

ラムダ式が使えない事情の場合は、foreachとかでゴリゴリしましょう。(諸事情により...)
jsonが諸事情でアレでしたら、XMLで同じことすればいいかなーとか。(諸事...(ry

ってか、VBラムダ式の方が先におぼえたのにもう完全に忘れてる。C#のノリでアローを書いてエラーになってこうなりました。
f:id:beachside:20150121112730p:plain

というかC#と違いすぎて、不思議と笑えました...。