Azureはじめました

Windows Azureで業務システムを組んでみる日記

BootstrapのGlyphIconを使うとwoffファイルで404がモリモリ出る話

In my case I was getting a 404 for glyphicons-halflings-regular.woff, and non visible glyphicons on mobile browsers.

I finally fixed it adding the MIME type on IIS:

.woff application/x-woff

Edit: Looks like there is some confusion about the MIME type for woff, more than one MIME type being accepted by different browsers, but the W3C says:

application/font-woff

Bootstrap 3 Glyphicons not working

woffはmime-typeで登録されてないのでIISが弾いてた。

解決法

web.configでmime-typeを指定しておけばいいらしい。

  <system.webServer>
    <staticContent>
      <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
      <mimeMap fileExtension=".woff" mimeType="application/x-font-woff" />
    </staticContent>
  </system.webServer>

svgもデフォルトでは未登録らしいので一緒に登録しとくといい。

BootstrapのGlyphIconを使うとリモートでアイコンが出ないという話

f:id:twisted0517:20140324151100p:plain
MVCでNuGet使ってBootstrapインストールするとこんな感じにCSSとフォントが配置される。

んで、CSSのロードをBundleConfigあたりでこんな感じに

        private static void RegisterStyleBundles(BundleCollection bundles) {
            bundles.Add(new StyleBundle("~/css")
                            .Include("~/Content/bootstrap/bootstrap.css")
                            .Include("~/Content/bootstrap/bootstrap-responsive.css")
                            .Include("~/Content/bootstrap/bootstrap-theme.css")
                            .Include("~/Content/bootstrap/dataTables.css")
                            .Include("~/Content/bootstrap-mvc-validation.css")
                            .Include("~/Content/bootstrap/signin.css")
                            .Include("~/Content/body.css")
                            .Include("~/Content/bootstrap-datepicker.css"));
        }

で、_layout.cshtmlあたりで

<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title - hogehoge</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    @Styles.Render("~/cs")
    @Scripts.Render("~/js")
</head>

みたいな感じにすると。

で、ローカルで実行してると普通に表示されるのに、いざサーバーで実行するとglyphiconが全部おべんとばこ(□)に化けてしまうっつー現象にやられた。

原因

リモートで実行してるアプリから送られてくるHTMLを見ると

<head>
    <meta charset="utf-8" />
    <title>Top - hogehoge</title>
    <link href="/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="/css?v=DO6j91cILO_L8-HWTgy7knOyUnxuUo4gQjQI7dSvpjg1" rel="stylesheet"/>
    <script src="/js?v=yQMfhDMNhFZ1m0ki0n3pWhCVm5vYHaVC1MllqiLohDc1"></script>
</head>

な、感じにcssのURLが短縮(?)される。

フォントの場所はbootstrap.css

@font-face {
  font-family: 'Glyphicons Halflings';
  src: url('../fonts/glyphicons-halflings-regular.eot');
  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');
}

相対パスで指定されてる。
css内のパスはCSSのURLがコンテキストパスとなった相対なので、上記HTMLだと

/../fonts/glyphicons-halflings-regular.*

を見に行ってめでたく404になると。

解決法

cssの実URLにある"/css"はBundleCollection.add()で登録したStyleBundleのラベルなので、ここを実URLに合うように変更すればOK。

  bundles.Add(new StyleBundle("~/css") ...
   ↓
  bundles.Add(new StyleBundle("~/Content/css/bootstrap") ...
<head>
  @Styles.Render("~/cs")
    ↓
  @Styles.Render("~/Content/css/bootstrap")
</head>

この時指定するラベル(/Content/css/bootstrap)と同じディレクトリがファイルシステム上実在するとそちらがロードされてしまうので注意。

というか

bootstrap.nugetで対処しておいて欲しいなぁ。

ロギングとか

MVC4でさくさくサービスを書いてるんだが、どうしてもちょっとしたミスで例外が出てたりしてその原因究明に追われたりするのはご愛嬌みたいなもんで。

しかし、いつまでもこんな状況なのも大変アレなのでまずはUnhandledExceptionを捕まえてログにきちんと吐かせるようにしようと。

UnhandledExceptionの捕まえ方

デスクトップアプリならApplication.ThreadExceptionハンドラあたりで捕まえればいいんだけど。
MVCだとControllerかFilterにイベントがあるんかなと調べたら大体ビンゴ。

The OnException Method The System.Web.Mvc.Controller class contains a method called OnException which is called whenever an exception occuts within an action. This does not rely on the HandleError attribute being set. If you're being a good coder and have your own base Controller class you can override this method in one place to handle/log all errors for your site.

ASP.NET MVC HandleError Attribute, Custom Error Pages and Logging Exceptions

Controller.OnExceptionをオーバーライドしてそこにロギングコードを埋めればいいと。

しかし、沢山あるコントローラーに一々コードを埋めるのも馬鹿らしいので、継承にサンドイッチコードでブチ込むことに。

    public class ErrorHandledController : Controller
    {
        protected override void OnException(ExceptionContext filterContext) {
            // Output a nice error page
            ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
            log.Error(filterContext.Exception);
            if (filterContext.HttpContext.IsCustomErrorEnabled) {
                filterContext.ExceptionHandled = true;
                this.View("Error").ExecuteResult(this.ControllerContext);
            } else {
                base.OnException(filterContext);
            }
        }
    }

大変ダサい。

AzureのSessionStateをSQLServerで管理する


一時的にEFのEntity保存してるとこがあってシリアライズに困って放置中('A`)

1つのトランザクションで同じエンティティを更新する?

入荷データを更新しながら一気に在庫データを更新するようなシチュエーションで、

	var list = <なんらかのソース>

	using (MyEntity entity = new MyEntity()){
		foreach (var source in list){
			Arrival arrival = new Arrival(){
				count = source.count ,
				: (データ転送など)
			};
			entity.arrivals.Add(arrival);

			//商品コードで検索とか
			Stock stock = entity.stocks.FirstOrDefault(st=>st.itemId == source.itemId);   
			if (stock==null){
				stock = new Stock(){itemId = source.itemId,};
				entity.stocks.Add(stock);
			}
			stock.count += count ;
		}
		entity.SaveChanges();
	}

こんな感じのコードはよくあるんだけど、source.itemIdが重複してるとエラーになる。

続きを読む