ハロの外部記憶インターフェイス

そろそろ覚える努力が必要かも…

npmだけで、jQueryパッケージ管理

パッケージ管理を1つ集中する方法の一つとして、npmにより、jQueryを制御する

前提として、npm(node.jsのパッケージ管理)はインストール済み

npm init

対象プロジェクトフォルダでnpmを初期化する。

$ npm init

結果として、jsonファイルが生成される。

{
  "name": "nvmtest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

jQueryのインストール

$ npm install jquery --save

node_modulesフォルダ作成され、中にjQueryがダウンロードされている。

scriptの作成

script.js

'use strict';

var $ = require('jquery');

$(function(){
    $('h1').css('color','red');
})

1つのスクリプト内で、jQueryをrequireして利用しているため、1ファイルだけで、全てを完結できる。

Html

上記で作成した、scriptを指定するだけ

<script type="text/javascript" src="script.js"></script>

参考

qiita.com

ASP.NET MVC ページングを実装

ASP.NET MVC上でページングを実装する。

Nuget

以下のパッケージを追加 * PagedList.Mvc

Controller

簡単にリストモデルをPagedListで返す様にするだけ、 * pageパラメータから、ページ番号を取得する。(最初は1) * returnのViewにToPagedList(ページ番号, 表示行数)を返す。

using PagedList;

public class HomeController
{
    public ActionResult Index(string page)
    {
        int pageNo = int.Parse(page ?? "1");
        List<MyModel> model = GetModelList();
        return View(model.ç);
    }
}

ViewModel

public class MyModel
{
    public string Name {get;set;}
    public string Address {get;set;}
}

HTML

View側のモデルをPagedListに設定する

Index.cshtml

@model PagedList.IPagedList<App.ViewModel.MyModel>
@using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />

<table class="table">
    <tr>
        <th>Name</th>
        <th>Address</th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Address)
            </td>
        </tr>
    }

</table>
<br/>
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

@Html.PagedListPager(Model, page => Url.Action("Index", new { page }))

最後の2行は以下のようなイメージで表示される。 f:id:haronoid:20180704191028p:plain

ページ番号をクリックするとIndexにpageが設定された形で次のページが呼び出される。

考えるところ…

EntityFrameworkをそのまま表示する場合、内部的に必要な部分だけ読み込んでくれるかもしれないが、 直接SQLを投げたりする場合は、このまますべて任せると全件読み取りになるため、パフォーマンス的には良くない。

ページング用のデータと、表示用のデータを別に実装したほうが良いかも

EntityFrameworkと連携する場合、もっと効率は良さそう

PagedList.IPagedList<App.ViewModel.MyModel> list;
list = ef.users.ToPagedList(pageNo, pageSize);

ASP.NET MVC ファイルのダウンロード

ASP.NET MVCでファイルをダウンロードする方法メモ

Controller サーバーのフォルダにファイルが存在する場合

public ActionResult Download()
{
    var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    return File(Server.MapPath("~/App_Data/dummy.xlsx"), contentType, "download.xlsx");
}

FileStreamからダウンロード

public ActionResult Download()
{
     MemoryStream memoryStream = new MemoryStream();
     using (FileStream fileStream = new FileStream(FilePath, FileMode.Open, FileAccess.Read))
     {
       fileStream.CopyTo(memoryStream);
     }
    var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    return File(memoryStream.ToArray(), contentType, "download.xlsx");
}

IE11の互換モード使用で、表示がおかしくなる

IE11とEdgeでの表示が違う

今時ながらの事だが、IE11を使っている現場で、しかも互換モードが適用されているみたく、作ったページがおかしくなるらしい。

対策

HTMLのmetaタグに以下の内容を追加した

<meta http-equiv="X-UA-Compatible" content="IE=edge" />

とりあえず、直ったみたいなので、メモっとく

ASP.NET MVCをIISの仮想フォルダに公開したら404エラーになる件

エラーの原因

ASP.NETのルーティングとJavascriptのURL実行部をIISの仮想フォルダまでは考慮していなかったため、ルーティングが失敗し、存在しないページを探しに行ってエラーになる感じ

エラーになる主な部分

  • HTML部のformactionとスクリプトソース設定の方が失敗していました。
<form method="post" enctype="multipart/form-data">
    <button itype="submit" formaction="/Home/Action1" >処理</button>
</form>
<script src="~/Scripts/IMyScript.js"></script>
  • javascriptは言うこともないが、パス合わなくなりますね。
    var ret = $.ajax({
        type: 'GET',
        url: '/Home/Action1',
        async: false
    }).responseText;

対応した部分

  • RouteConfigに仮想フォルダ用のルーティングを追加
routes.MapRoute(
    name:="SUB",
    url:="SUB/{controller}/{action}/{code}",
     defaults:=new {controller = "Home", action = "Index", code = UrlParameter.Optional}
)
  • View部分には@Url.Contentを使用
<form method="post" enctype="multipart/form-data">
    <button itype="submit" formaction='@Url.Content("~/Home/Action1")' >処理</button>
</form>
<script src='@Url.Content("~/Scripts/IMyScript.js")'></script>

*JavascriptにはルートのUrlを再生性するため、_Layoutにルート情報を隠しといて再生成関数を配置

<input id="hdnRootUrl" type="hidden" value='@Url.Content("~/")' />
var myurl = $('#hdnRootUrl').val() +  '/Home/Action1';
myurl.replace('//', '/');
 var ret = $.ajax({
     type: 'GET',
     url: myurl,
     async: false
 }).responseText;

ASP.NET ファイルアップロード関連トラブル

ファイルアップロード時、以下のエラーに遭遇

  • maxAllowedContentLength エラー
  • 要求の長さの最大値を超えました。 POSTされるファイルの最大サイズが引っかかる場合、発生。 maxRequestLengthが足りない場合起きるエラー 大容量のCSVファイルなどは最大容量で引っかかるらしい、 以下の様に、httpRuntimeに最大設定で回避
    <system.web>
      <httpRuntime maxRequestLength="65535"/>
    </system.web>

IIS7以降ではサーバの要求フィルター設定項目でも、ファイルサイズの 上限を設定する必要がある。らしい

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="120000000"/>
      </requestFiltering>
    </security>
  </system.webServer>

CsvHelperを利用して、Csvデータを取り込む

Nugetより、CsvHelperをインストールする。

Csvを読み取り、モデルに設定してくれるパッケージ まあ、便利そうだから入れる。

Csvファイルサンプル

Code,Name
001,Tokyo
002,Osaka
003,Nagoya
004,Hakata
005,Yokohama

Csv取込用モデル作成

Public class MyData {
    Public string Code {get; set;}
    Public string Name {get; set;}
}

Csvファイルを読み取る

Public void main() {
    Dim fs As FileStream = System.IO.File.Open("csv_data\\testcsv.csv", FileMode.Open)

    using(var sr = new StreamReader(fileStream, System.Text.Encoding.GetEncoding("shift_jis"))
    {
        var cr = new CsvHelper.CsvReader(sr);
        While(csvReader.Read()){
             var data = csvReader.GetRecord(Of MyData)()
        }
    }
}

注意点

CsvHelperでモデルにバインドする場合は、ヘッダーにモデルの項目名と一致しないとエラーになるため、注意が必要