Quantcast
Channel: かずきのBlog@hatena
Viewing all 1387 articles
Browse latest View live

ASP.NET 空の Web アプリケーションからWebAPIを使えるようにするための道のり「作成からヘルプページ、ODataのクエリの有効化まで」

$
0
0

やってみましょう。デフォルトのWebAPIのだといっぱいなにかついてくるので。

プロジェクトの作成

ASP.NET 空の Web アプリケーションを作りましょう。それだけ。

必要な参照の追加

NuGetから参照を追加します。

  • Microsoft.AspNet.WebApi

この1つで芋づる式に必要なものがついてきます。
f:id:okazuki:20130823215140p:plain

Global.asaxを追加

グローバルアプリケーションクラスを追加します。
f:id:okazuki:20130823215309p:plain

App_Startというフォルダを作って、WebApiConfigクラスを作ってWebAPIの設定を行います。

using System.Web.Http;

namespace WebApplication1
{
    publicstaticclass WebApiConfig
    {
        publicstaticvoid Register(HttpConfiguration configuration)
        {
            configuration.Routes.MapHttpRoute(
                "DefaultApi",
                "api/{controller}/{id}",
                new { id = RouteParameter.Optional });
        }
    }
}

これをGlobal.asaxのApplication_Startから呼んでやります。

protectedvoid Application_Start(object sender, EventArgs e)
{
    WebApiConfig.Register(GlobalConfiguration.Configuration);
}

動作確認

Controllersフォルダを作って、その中にWeb API コントローラー クラスを作ります。名前はとりあえずここではValuesControllerにしました。
f:id:okazuki:20130823220145p:plain

実行して、ブラウザが立ち上がるのでブラウザは無視してFiddlerあたりからhttp://localhost:ポート/api/valuesにアクセスしてみます。
f:id:okazuki:20130823220541p:plain

ちゃんと結果が返ってきます。
f:id:okazuki:20130823220638p:plain

ヘルプページの準備

ASP.NET WebAPIのヘルプページを準備してみます。以下のパッケージをnugetで追加します。

  • Microsoft.AspNet.WebApi.HelpPage

参照と、以下のようなファイル群が追加されます。こいつはASP.NET MVCで作られてるっぽいので、App_StartフォルダにRouteConfigというクラスを作って以下のような感じのコードを書きます。

using System.Web.Mvc;
using System.Web.Routing;

namespace WebApplication1
{
    publicstaticclass RouteConfig
    {
        publicstaticvoid RegisterRoutes(RouteCollection routes)
        {
            // axdは対象外らしい
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            // デフォルトのMVCのルートを定義
            routes.MapRoute(
                "Default",
                "{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional });
        }
    }
}

Global.asaxのApplication_Startで上記のRegisterRoutesメソッドを呼び出します。それと同時にヘルプページはMVCのエリアの機能を使ってるので、それも有効にするためAreaRegistration.RegisterAllAreasメソッドを呼び出します。RouteConfigはWebApiのURLを横取りしないようにWebApiConfigより後に記述するのがポイント。

protectedvoid Application_Start(object sender, EventArgs e)
{
    // MVCのエリアを登録する
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
}

実行して以下のURLにアクセスするとヘルプページが表示されます。ばっちり!
http://localhost:ポート/Help/
f:id:okazuki:20130823222244p:plain

ODataによるクエリを有効化する

最後にWebAPIに対してODataのクエリによるフィルタリングとかの機能を追加したいと思います。
nugetで以下のものを参照に追加します。

  • Microsoft.AspNet.WebApi.OData

参照を追加したらHttpConfigurationの拡張メソッドとしてODataのクエリを有効化するメソッドが追加されるので、それをWebApiConfigで呼び出します。

using System.Web.Http;

namespace WebApplication1
{
    publicstaticclass WebApiConfig
    {
        publicstaticvoid Register(HttpConfiguration configuration)
        {
            configuration.Routes.MapHttpRoute(
                "DefaultApi",
                "api/{controller}/{id}",
                new { id = RouteParameter.Optional });

            // ODataによるクエリをサポート
            configuration.EnableQuerySupport();
        }
    }
}

WebAPI自体をODataのクエリに対応させるには、さらにメソッドの戻り値をIEnumerableからIQueryableに変更しないといけません。ValuesControllerのGetメソッドの戻り値を以下のように変更します。

// GET api/<controller>public IQueryable<string> Get()
{
    returnnewstring[] { "value1", "value2" }.AsQueryable();
}

実行して動作を確認してみます。一件だけ結果を返すように?$top=1をつけてAPIを呼び出してみます。
f:id:okazuki:20130823223155p:plain

結果を見ると、ちゃんと最初の1件だけとれてることわかります。ばっちりですね。
f:id:okazuki:20130823223436p:plain

以上ゼロからWebAPIでODataのクエリが使えるようになるまでの手順でした。以外とめんどい。あとはフィルタの設定あたりを足せば普通のWebAPIのテンプレートと大体似たような雰囲気になるかも。


ItemTemplate内のプロパティをViewStateによって変える

自力Basic認証のやり方

$
0
0

Basic認証の、さらに自力だなんて最後の手段だと思うけどメモ…。とりあえず参考にしたサイト

やったこと

Web.configに以下の記述を追加。

<authentication mode="None" /><authorization><deny users="?"/></authorization>

そして、Global.asaxのAuthenticateRequestで以下のような処理をします。

protectedvoid Application_AuthenticateRequest()
{
    if (string.IsNullOrEmpty(this.Request.Headers["Authorization"]))
    {
        // Basic認証だよ!っていう情報を返しておくthis.Response.StatusCode = 401;
        this.Response.SubStatusCode = 1;
        this.Response.AppendHeader("WWW-Authenticate", "Basic");
        this.CompleteRequest();
        return;
    }
            
    // とりあえず、なんか認証情報きてたら認証OKってことにしとく。// 本当は参考URLの方法でユーザーIDとパスワードをとってきちんと認証しようね!
    Debug.WriteLine(this.Request.Headers["Authorization"]);
    HttpContext.Current.User = new GenericPrincipal(new GenericIdentity("user"), new[] { "Users" });
}

使いたい製品が基本認証以外をサポートしてるんなら、ほかの方法にするのがいいんだけどね…。

ASP.NET MVCの個人的なメモ。テンプレートとか、共通的に使うViewとか

$
0
0

ASP.NET MVC弱者なのがつらい今日この頃。ASP.NET MVCの基本のテンプレートを見ながら少しだけ構造をメモっておこうと思います。主にViewまわり

  • Views
    • Shared
      • _Layout.cshtml
      • Error.cshtml
    • _ViewStart.cshtml
    • Web.config

_Layout.cshtml

ページのテンプレートになる人。中身はこんなかんじ。

<!DOCTYPE html><html><head><metacharset="utf-8" /><metaname="viewport"content="width=device-width" /><title>@ViewBag.Title</title>    @Styles.Render("~/Content/css")    @Scripts.Render("~/bundles/modernizr")</head><body>
    @RenderBody()

    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
</body></html>

@RenderBody()で、このテンプレートを使ったページの本体を出力しつつ、@RenderSection(セクション名, required: 必須かどうか)を使って、メインのボディ部分以外も、このテンプレートを適用した人でカスタマイズできるようにしている。

因みにセクションの部分はテンプレートを適用したViewで@section セクション名 { ... }のようにして書くことができる。Razorすっきりかけていいよ。例えば以下のような感じ。

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

@section scripts {
    <scripttype="text/javascript">        $(function(){            $('h2').text("Hello jQuery");});</script>
}

Error.cshtml

エラーページ。FilterConfigでグローバルに指定されているHandleErrorAttributeがデフォルトで表示するエラーページ。MSDNにもがっつりかいてある。

既定では、HandleErrorAttribute 属性を設定されたアクション メソッドが例外をスローすると、MVC は ~/Views/Shared フォルダーにある Error ビューを表示します。 

_ViewStart.cshtml

名前の通りViewの最初に自動で埋め込むやつ。さっき説明した_Layout.cshtmlは、ここでLayoutに指定されてるから特に何もしない場合は自動で適用されるという仕掛け。

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

Web.config

アプリケーションのルートにあるWeb.configではないことに注意。おそらく、Viewsフォルダの下にあるcshtmlを隠すことが主な目的だと思われる…。以下のような記載があるので。

<httpHandlers><add path="*"verb="*"type="System.Web.HttpNotFoundHandler"/></httpHandlers>

まとめ

ViewsのSharedとか_Layoutとか_ViewStartとか、空で作るといつも名前なんだっけ…ってなるので個人的なメモでした。
プロジェクトテンプレートは、なんだこんなにコード吐きやがって!!と思っても、これだけのコードを吐くということは、作成者側に何らかの意図があるということなので理解したうえで、捨てるなら捨てるというのがよろしいかと思います。

Web API + Form認証

$
0
0

メンバーシッププロバイダーとか実装したくないですはい。ということで認証かけてないWebAPIを1個置いといて、その中で認証チケットの発行という感じかなあ。

Web.configでフォーム認証を有効かするためにsystem.webの下に以下の要素を追加

<authentication mode="Forms" />

こんな感じのクラスをクラスライブラリに定義しておいて…(ポータブルライブラリがいいかな)

using System.Runtime.Serialization;

namespace AuthApiTest.Models
{
    [DataContract]
    publicclass LoginParameter
    {
        [DataMember(Name = "loginId")]
        publicstring LoginId { get; set; }
        [DataMember(Name = "password")]
        publicstring Password { get; set; }
    }
}
using System.Runtime.Serialization;

namespace AuthApiTest.Models
{
    [DataContract]
    publicclass LoginResult
    {
        [DataMember(Name = "userName")]
        publicstring UserName { get; set; }
    }
}

こんな感じのWebAPIをおいとく。*1

using AuthApiTest.Models;
using System.Net;
using System.Web.Http;
using System.Web.Security;

namespace AuthApiTest.Controllers
{
    publicclass AuthController : ApiController
    {
        public LoginResult Post(LoginParameter param)
        {
            if (param.LoginId == "user"&& param.Password == "p@ssw0rd")
            {
                FormsAuthentication.SetAuthCookie("user", false);
                returnnew LoginResult { UserName = "田中" };
            }

            // こういうとき、何番返すのが妥当なんだろうかthrownew HttpResponseException(HttpStatusCode.BadRequest);
        }
    }
}

認証かかったAPIとしてValuesControllerというのも作っておきます。

using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace AuthApiTest.Controllers
{
    // 認証しないと呼べないよ~
    [Authorize]
    publicclass ValuesController : ApiController
    {
        public IEnumerable<string> Get()
        {
            return Enumerable.Range(1, 10).Select(i => "value" + i);
        }
    }
}


お膳立てはできたのでクライアント側です。今回はコンソールアプリケーションでいってみます。コンソールアプリケーションには、LoginParameterやLoginResultクラスを定義したライブラリを追加しておきます。あとは、HttpClientの最新のやつをNuGetからいれておきます。PostAsAsyncとかのAPIがあるとすごい楽なので。

  • Microsoft.AspNet.WebApi.Client

あとは、ログインして呼び出してみる。こんな感じに書いてみました。ストアアプリもHttpClientのリリース前のバージョンだと、PostAsJsonAsyncとかあって便利。早く正式こないかなぁ。

using AuthApiTest.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;

namespace AuthApiTest.Client
{
    class Program
    {
        staticvoid Main(string[] args)
        {
            var cookie = new CookieContainer();
            Console.WriteLine("-------");
            {
                // 認証して通信
                var client = Create(cookie);
                var response = client.PostAsJsonAsync("http://localhost:3502/api/auth",
                    new LoginParameter
                    {
                        LoginId = "user",
                        Password = "p@ssw0rd"
                    }).Result;
                Console.WriteLine(response.Content.ReadAsAsync<LoginResult>().Result.UserName);
                var response2 = client.GetAsync("http://localhost:3502/api/values").Result;
                // 失敗してたら例外とばす
                response2.EnsureSuccessStatusCode();

                Console.WriteLine(response2.Content
                    .ReadAsAsync<IEnumerable<string>>()
                    .Result
                    .Aggregate((c, a) => c + ", " + a));
            }
            Console.WriteLine("-------");
            {
                // 認証してないと失敗する確認
                var client = Create(new CookieContainer());
                var response = client.GetAsync("http://localhost:3502/api/values").Result;
                try
                {
                    // 失敗してたら例外とばす
                    response.EnsureSuccessStatusCode();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

            }
            Console.WriteLine("-------");
            {
                // cookie containerさえ共有してればおk// 認証して通信
                var client = Create(cookie);
                var response = client.GetAsync("http://localhost:3502/api/values").Result;
                // 失敗してたら例外とばす
                response.EnsureSuccessStatusCode();

                Console.WriteLine(response.Content
                    .ReadAsAsync<IEnumerable<string>>()
                    .Result
                    .Aggregate((c, a) => c + ", " + a));
            }
        }

        // HttpClient作るよprivatestatic HttpClient Create(CookieContainer cookie)
        {
            returnnew HttpClient(new HttpClientHandler { CookieContainer = cookie });
        }
    }
}

実行結果は以下のようになります。

-------
田中
value1, value2, value3, value4, value5, value6, value7, value8, value9, value10
-------
Response status code does not indicate success: 401 (Unauthorized).
-------
value1, value2, value3, value4, value5, value6, value7, value8, value9, value10

*1:パスワードは平文で保存しちゃだめよ

パスワードをハッシュ化する方法(.NET 4.5とWinRT)

$
0
0

先の記事で、パスワードを平文で保存したらダメという旨を記載したのですが、じゃぁ具体的にどうやるのよ?という例をコードレシピにあげてみました。正直ここらへんは、素人なので突っ込みがあったらコメントくださいm(_ _)m

パスワードをハッシュ化する方法(.NET4.5 & WinRT)

はてなブログをはてな記法からMarkdownに変更してみた

$
0
0

悪くない

ちょっと気分転換もかねて、はてなでしか通じないはてな記法じゃなくてMarkdownに切り替えてみた。コードのハイライトもいけるし。

Console.WriteLine("Hello world");

googleみたいにリンクもいけるし。

画像もいけるっぽいし(これは、はてな記法と変わらないんですね) f:id:okazuki:20130829082413j:plain

Markdownの記法でURLを直指定で画像をとるほうほうは… 画像はどうでしょう

title1title2title3
表もいけるっぽいですね!

あとはhrとか


引用記法とかもいけるのかな

  • リスト
  • 表示
  • とか
    • いける

番号付っと

  1. 数字の
  2. リストも
    1. いけるのか
    2. 確認
  3. してみる

参考にしたサイト

パスワードをハッシュ化する方法(.NET 4.5とWinRT) 訂正


ASP.NET WebAPIでODataクエリの美味しいところだけいただく方法

$
0
0

ページングとか、最大取得件数とかソートとかetc...そこらへんとかは、誰が実装しても同じようなコードになるので提供されているライブラリで楽して実装したい。そういうのが人情だと思います。今回はASP.NET WebAPIのOData対応の機能を使ってソート、フィルター、ページングなどの処理をODataのクエリにお任せしてしまう方法をちょろっとやってみようと思います。

ODataQueryOptionsクラス

そういう役目をしてくれるクラスがWebAPIのODataの機能の中にばっちりいたりします。

こいつをODataのクエリを有効にしたWebAPIの引数で受け取るようにすると勝手にクエリを解釈した結果が入ってます。ODataのクエリを有効化するには以下の方法でさくっとやっちゃいましょう。 - ASP.NET 空の Web アプリケーションからWebAPIを使えるようにするための道のり「作成からヘルプページ、ODataのクエリの有効化まで」

上記の方法は、空のテンプレートからですがASP.NET MVC4のプロジェクトを作ってWebAPIのテンプレートを選択して、WebApiConfigで以下の一行のコメントを外すでもOKです。

config.EnableQuerySupport();

さて、ODataQueryOptoionsを使うと何が嬉しいかというと、このオブジェクトをRepositoryあたりまで引数で渡してやると、ApplyToメソッドでIQueryableに対してODataで設定された条件を指定してくれること…!自前でパラメータ解析しなくていい点がいいですね。よくある、ControllerクラスにDbContextとか持たせてる方法だと、あんまり気にしなくてもいいですが、Controllerの下に何層かレイヤがあるときは、IQueryableに対する操作をControllerでしたくないということもあると思いますので、こいつを使うのがいいと思います。

さっそく使ってみましょう。

コントローラーの前にコントローラーから呼び出す予定のクラスを作ります。なんとんく、こいつにODataQueryOptionsを直で渡すのは、いやだったので、ラムダ式でフィルタを追加で指定できるようなシグネチャにしてみました。name引数で受け取った値をもとに絞り込み条件を設定したあとに、optionalFilterに値が設定されていたら、IQueryable<Person>を渡して追加処理を行います。

publicclass PeopleService
{
    privatestaticreadonly IList<Person> Store = Enumerable.Range(1, 100)
        .Select(i => new Person { Id = i, Name = "tanaka" + i })
        .ToList();

    public IQueryable<Person> GetPerson(
        string name,
        Func<IQueryable<Person>, IQueryable<Person>> optionalFilter = null)
    {
        var q = Store.AsQueryable()
            .Where(p => p.Name.Contains(name));
        if (optionalFilter != null)
        {
            q = optionalFilter(q);
        }

        var list = q.ToList();
        return list.AsQueryable();
    }
}

publicclass Person
{
    publicint Id { get; set; }
    publicstring Name { get; set; }
}

あとは、コントローラーだけです。サービスを呼ぶだけの簡単な感じで。

publicclass PeopleController : ApiController
{
    private PeopleService service = new PeopleService();

    public IQueryable<Person> Get(ODataQueryOptions<Person> options, string name)
    {
        returnthis.service.GetPerson(
            name,
            optionalFilter: q => options.ApplyTo(q) as IQueryable<Person>);
    }
}

ODataQueryOptions<Person>を引数で受け取ってApplyToメソッドを使ってOData関連のクエリをお任せしています。もちろんOData以外のパラメータを受けることはできるので、nameという引数も追加してみました。こいつを実行してFiddlerあたりから軽く呼び出してみます。名前にa1を含む人を3人とか

orderbyしてみたりとか

ばっちり動きますね!あとはクライアント側で、このクエリ文字列を組み立てるのが簡単にできたら文句ないんですが…。

PCL版のHttpClientが物足りないのでメソッドを生やした

Fakes FrameworkとMoqめもめも

$
0
0

Fakes Framework一択でもいいけど、Premium以上なのよね~。高いわ~。ということで、現実解はMoq。

Fakesのほうがよさげな点

staticなメソッドや非virtualなメソッドとかも差し替え出来る。テスト?なんですかそれ?というようなコードでも強引にモックに差し替え出来る。

Moqのほうがよさげな点

モックのメソッドが意図したとおりに、使われたかの確認が出来る。

お試し

こんなテスト対象のクラスがあったとして。

publicclass Calc
{
    publicvirtualint Add(int x, int y) { return x + y; }
}

テストコードは各々こんな感じになる。

[TestClass]
publicclass UnitTest1
{
    [TestMethod]
    publicvoid ShimsMethod()
    {
        using (ShimsContext.Create())
        {
            ShimCalc.AllInstances.AddInt32Int32 = (c, x, y) =>
            {
                Assert.AreEqual(10, x);
                Assert.AreEqual(20, y);
                return10;
            };
            Assert.AreEqual(10, new Calc().Add(10, 20));
        }
    }

    [TestMethod]
    publicvoid StubMethod()
    {
        var stub = new StubCalc
        {
            AddInt32Int32 = (x, y) =>
            {
                Assert.AreEqual(10, x);
                Assert.AreEqual(20, y);
                return10;
            }
        };

        Assert.AreEqual(10, stub.Add(10, 20));
    }

    [TestMethod]
    publicvoid MoqMethod()
    {
        var moq = new Mock<Calc>();
        moq.Setup(c => c.Add(10, 20)).Returns(10);

        Assert.AreEqual(10, moq.Object.Add(10, 20));
        moq.VerifyAll();
    }
}

FakesのStubとMoqのMockを比べるとMoqのほうが高機能っぽい(意図したとおりの呼び出されたかどうかの確認が出来る点で)ですが、Shimsは、ShimsContextの中だったら、staticなメソッドだろうと非virtualなメソッドだろうと、結果を差し替えることが出来る。

上のコードの中では、ShimsMethodだけがCalcクラスのAddがvirtualじゃなくても動作する。あとはSystemu名前空間のクラスとかもShimsで呼び出し結果を意図したものに差し替え出来る。何それ怖い。

個人的なまとめ

Premium以上ならおとなしくFakes使ったほうが強力っぽいし、無駄にインターフェース作ったりとかしなくてもテストは可能になるあたり、つぶしが効きそう。Moqでもテストできるような形(Interfaceきっとくとかvirtualにしておくとか、DateTime.Nowとかはラップしたものを用意しておくとかetc...)にする条件(人的にもお金的にも体制的にも…)が整ってるならMoqでいいんじゃにあかなぁとまとまりのないことを書きましたが、端的にいうとMoqとFakesの記憶を将来の自分が辿るためのコード片メモでした。

リンク

UnityのLifetimeManagerをカスタマイズする

$
0
0

CodePlexにBlogのタイトルのサンプルを公開しました。

LifetimeManagerを見てみて感じたのは、本当にLifetimeManagerはオブジェクトの生存期間の管理という役割に特化してるんだなあと思いました。ほんと、きれいに役割分担されてるクラス構造に感服。

VS2013のLightSwitch HTMLClientでテーブルがサポートされた…!

$
0
0

いや、今までもカスタムコントロールで出来たっちゃぁできたんですが、データの表示方法に普通にTableってあって、それを選んだらテーブルになるっていうお手軽さは最高です!

f:id:okazuki:20130910194921j:plain

デフォルトの見た目はこんなかんじ。タイルとかリストと同じようにタップしたときのアクションとかも指定できるので、今までと同じノリで作れます。

f:id:okazuki:20130910195011j:plain

なかなかいい!

Windows 8のストアアプリをとりあえずWindows 8.1対応する方法(間違ってた)

$
0
0

訂正

Windows 8.1にリターゲットするだけで、それなりに対応してくれました。 http://www.atmarkit.co.jp/ait/articles/1308/29/news069.html

以下の間違ってる内容は、標準の挙動じゃ満足できない場合にのみやるのがいいかと…。例えば、縦長をデフォルトだとポートレイトになるのをFilledにしたいとか。

以下間違ってる内容

Windows ストア アプリのデフォルトのテンプレートに沿って作ってる人は、大体LayoutAwarePageを継承して作成しているはずです。このLayoutAwarePageには、Windows 8の頃は状況に応じて適切なApplicationViewStateを使ってVisualStateを変更してくれるのですが、こいつが8.1でまさかの非推奨。スナップなんて無かった状態になってしまいます。

f:id:okazuki:20130910220354p:plain

こいつをどうにかする方法として、LayoutAwarePageを使ってる人が一番簡単にWindows 8.1上でもそれなりに動くようにする方法をちょっと考えてみました。

LayoutAwarePageを見てみる

LayoutAwarePageでは、Windowのサイズ変更などのタイミングでVisualStateを変更しています。この時VisualStateの名前を決定しているメソッドが、LayoutAwarePageのDetermineVisualStateになります。

/// <summary>/// <seecref="ApplicationViewState"/>値を、ページ内の表示状態管理で使用できる文字列に/// 変換します。既定の実装では列挙値の名前を使用します。/// サブクラスでこのメソッドをオーバーライドして、使用されているマップ スキームを制御する場合があります。/// </summary>/// <paramname="viewState">表示状態が必要なビューステート。</param>/// <returns><seecref="VisualStateManager"/>の実行に使用される/// 表示状態の名前</returns>/// <seealsocref="InvalidateVisualState"/>protectedvirtualstring DetermineVisualState(ApplicationViewState viewState)
{
    return viewState.ToString();
}

ここを、単純にApplicationViewStateを文字列化しているのをやめて、表示されてる状態に応じて適切なVisualStateを返してやることで、Windows 8.1でもそれなりに動くようになります。例えば、以下のように書き換えてみるといいかも??

/// <summary>/// <seecref="ApplicationViewState"/>値を、ページ内の表示状態管理で使用できる文字列に/// 変換します。既定の実装では列挙値の名前を使用します。/// サブクラスでこのメソッドをオーバーライドして、使用されているマップ スキームを制御する場合があります。/// </summary>/// <paramname="viewState">表示状態が必要なビューステート。</param>/// <returns><seecref="VisualStateManager"/>の実行に使用される/// 表示状態の名前</returns>/// <seealsocref="InvalidateVisualState"/>protectedvirtualstring DetermineVisualState(ApplicationViewState viewState)
{
    var view = ApplicationView.GetForCurrentView();
    if (view.IsFullScreen)
    {
        return  view.Orientation == ApplicationViewOrientation.Portrait ?
            "FullScreenPortrait":
            "FullScreenLandscape";
    }

    var w = Window.Current;
    var width = w.Bounds.Width;
    return width == 320 ? "Snapped" : "Filled";
}

そして、Windows 8.1では、デフォルトでアプリの幅は500pxになってるので折角対応しているスナップ表示がいかせないので、appxmanifestを開いて最小幅を320pxにします。

f:id:okazuki:20130910221255p:plain

この変更を、Windows 8 ストア アプリ開発入門のサンプルプログラムのRSSリーダーに適用するとこんな感じになります。

全画面表示は当然OK

f:id:okazuki:20130910221429p:plain

縦にしてもOK

f:id:okazuki:20130910221500p:plain

中途半端な大きさもOK

f:id:okazuki:20130910221626p:plain

スナップ?もOK

f:id:okazuki:20130910221348p:plain

ということで

とりあえずの対応としては十分っぽい。

ログインダイアログを出したい

$
0
0

Windows ストア アプリでログインダイアログ出したい!ってときに使えるクラス。

CredentialPicker Class

使い方は結構簡単でした。

var option = new CredentialPickerOptions
{
    AuthenticationProtocol = Windows.Security.Credentials.UI.AuthenticationProtocol.Basic,
    Message = "Message Text",
    Caption = "Caption Text",
    TargetName = "オレオレ",
    CredentialSaveOption = CredentialSaveOption.Selected,
};
var p = await CredentialPicker.PickAsync(option);
// ユーザー名をパスワードを取得
Debug.WriteLine(p.CredentialUserName);
Debug.WriteLine(p.CredentialPassword);

AuthenticationProtocolは、いろんなものが設定できますが、ここではパスワードをそのまま取得できるBasicを指定してます。私は、そこらへん明るくないのですが、色んな値が設定できるので用途に応じて好きにできそう

AuthenticationProtocol Enumeration

出てくるログイン画面はそっけないものですが独自に作りこむよりはOSになじんでいいかも。

f:id:okazuki:20130911214240p:plain

PickAsyncの戻り値の、Credentialプロパティで入力された"不透明な資格情報"が取得できます。

CredentialPickerResults.Credential credential Property.aspx) 不透明な資格情報が何をさしているのかわかりませんが、こいつを記憶しておくことで再度ログインダイアログを出すときに資格情報をあらかじめ入力された状態にすることができます。 IBuffer型なので、AsStreamメソッドを使ってストリームに変換してどこかに書き出しておいてもいいですし、お好きにできます。

ログイン画面にあらかじめ資格情報が入った状態にするには、CredentialPickerOptionsのPreviousCredentialに、上記のCredentialPickerResults.Credentialプロパティの値をつっこめば出来ます。

知らなかった。


Windows 8.1のストアアプリで予定を追加しようとしたけれど

$
0
0

AppointmentManagerというクラスを使うと簡単に予定を追加できそうな様子を醸し出しています。

AppointmentManager class

使い方は簡単。Appointmentクラスに情報をつっこんでShowAddAppointmentAsyncメソッドを呼ぶだけ。コードとしては以下のような感じ。

var appo = new Appointment
{
    StartTime = DateTimeOffset.Now,
    AllDay = true,
    Subject = "テスト用予定"
};

// ShowAddAppointmentAsyncで表示されるUIの参考として、この操作をしたきっかけの// コントロールの矩形を渡してやる必要があるみたいなので取得する
var element = (FrameworkElement) sender;
var t = element.TransformToVisual(null);
var rect = t.TransformBounds(new Rect(0, 0, element.ActualWidth, element.ActualHeight));

var appointmentId = await AppointmentManager.ShowAddAppointmentAsync(
    appo, 
    rect,
    Placement.Default);

// 戻り値は、登録したAppointmentを識別するためのID
var dlg = new MessageDialog(appointmentId);
await dlg.ShowAsync();

ShowAddAppointmentAsyncの戻り値は、あとでAppointmentを更新したり消したりするときに使うIDらしいので、大事にとっとく必要があります。

ただ2013/09/11現在では、このAppointmentManager.ShowAddAppoitmentAsyncを読んだときに処理を引き取ってくれるAppointmentProviderがいないみたいなので、以下のような悲しい結果になります。正式リリースの10月には、カレンダーアプリが正式対応してるとうれしいなぁ。

f:id:okazuki:20130911221245p:plain

Windows Azure仮想マシンのWindows ServerとVisual Studioの日本語化メモ

$
0
0

結構前からですがVisual Studio 2013 Previewが入ったイメージがAzureの仮想マシンで提供されています。おそらく、今後もこのような形で"英語版"が提供されると思うので日本語化までの手順をまとめておこうと思います。

仮想マシンの作成

ここらへんは、迷うことはないと思います…。 今回仮想マシンとしてギャラリーにある中から以下のものを作成しました。

  • Visual Studio Ultimate 2013 Preview

RDP接続の確認

仮想マシンが完成したらRDP接続のためのファイルをダウンロードして準備完了です。

f:id:okazuki:20130912153539j:plain

ここまで、30分もかかってないなんていい時代になりました。

とりあえず日本語化

Win + Xからコントロールパネルを選択します。

f:id:okazuki:20130912111355j:plain

コントロールパネルでLanguageで検索するとAdd a languageが出てくるので選択します。間違っても、膨大なコントロールパネルの設定項目から探そうと思ってはいけません。検索しましょう!

f:id:okazuki:20130912111546j:plain

そしてもういっちょAdd a languageを選択

f:id:okazuki:20130912111643j:plain

言語を選択する画面が出てくるので右上の検索ボックスからJapanとかうちこんでJapaneseを検索して選択してAddボタンを押します。

f:id:okazuki:20130912111810j:plain

日本語を選んでMove upして一番上に持っていきます。

f:id:okazuki:20130912111854j:plain

日本語のoptionsを選んでDownload and install language packを選択しましょう。

f:id:okazuki:20130912112010j:plain

しばらく待ってるとInstallation completeとでるのでCloseしましょう。

次に、再起動をしましょう。ファイル名を指定して実行(Win + R)でpowershell restart-computerってうつのが最近好きです。

f:id:okazuki:20130912115118j:plain

再起動が完了すると、日本語になってます。

f:id:okazuki:20130912115604j:plain

タイムゾーンも日本時間に変えるためにコンパネでタイムゾーンの変更を選択します。

f:id:okazuki:20130912115815j:plain

UTCになってるので日本に変更しましょう。

f:id:okazuki:20130912115901j:plain

Visual Studio 2013 Previewの日本語化

OSが日本語になったからといってVisual Studioは英語のままなので、言語パックをインストールします。Visual Studio 2013 Previewの仮想マシンは、IEセキュリティ機能の厚生は無効になってるように見えますが、Administratorsグループだけ有効になってるのでIEを管理者として実行して下記リンクからダウンロードするか、IEセキュリティ機能をUsersグループにたいしても無効にしてからダウンロードします。今回はIEを管理者として実行してダウンロードしました。

ライセンス条項に同意して、いつも疑問に思ってるのですが、無駄にでかいインストールリンクを押してインストールします。

f:id:okazuki:20130912121735j:plain

Visual Studioの日本語化の確認

Visual Studioの日本語化パックのインストールが終わったら、TOOLSメニューのOptionsからEnvironmentのInternational Settingsを選択して日本語を選びます。

f:id:okazuki:20130912123847j:plain

Visual Studioを再起動すると日本語化完成です。

f:id:okazuki:20130912153258j:plain

Windows 8.1のストアアプリで追加されたフライアウトのサンプル書きました

$
0
0

コードレシピにWindows 8.1のストアアプリで追加されたFlyoutのサンプルコードをアップしました。 個人的には、Popupを使って地道にやってたことが、簡単にできるようになってるのでFoyoutコントロールの追加は大歓迎です。ただ、画面右からにょきっとのびてくるフライアウトは無いです…。

Windows 8.1のストアアプリで追加されたFlyoutの使用例

AlertDialogで背景のグレーになっている箇所をタップすると閉じるようにしたい

$
0
0

AlertDialog.Builderでダイアログを組み立てたあとにcreate()で取得したAlertDialogに対してsetCanceledOnTouchOutside(true)でいけるみたい。

package com.example.helloworld;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;

publicclass MainActivity extends Activity {

    @Overrideprotectedvoid onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Overridepublicboolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        MenuItem item1 = menu.findItem(R.id.item1);
        item1.setOnMenuItemClickListener(new OnMenuItemClickListener() {
            @Overridepublicboolean onMenuItemClick(MenuItem item) {
                AlertDialog.Builder b = new AlertDialog.Builder(MainActivity.this);
                b.setTitle(R.string.app_name);
                b.setMessage(R.string.alert_message);
                b.setCancelable(true);
                b.setInverseBackgroundForced(true);
                
                AlertDialog d = b.create();
                // ここでセットするらしい
                d.setCanceledOnTouchOutside(true);
                d.show();
                returntrue;
            }
        });
        returntrue;
    }

}

ふむぅ。慣れないと難しいですな…Android。

Outlook 2013で受信メールの大半が文字化けしてたのをなおしたい

$
0
0

Outlook 2013が最近受信メールのほとんどで文字化けするようになりました。

f:id:okazuki:20130916120737p:plain

とりあえず、文字化けしたメッセージをダブルクリックして開いてリボンのメッセージからアクション→その他のアクション→エンコード→Unicode(UTF-8)にすると文字化けがなおりました。

f:id:okazuki:20130916120837j:plain

ただ、毎回毎回この手順を踏むのはめんどくさいので、ファイルのオプションの詳細設定にある文字設定オプションが日本語(JIS)になってたのを(前からそうなってたのかは謎)Unicode(UTF-8)にしました。

f:id:okazuki:20130916121157p:plain

文字化けしてたメールをひらいても文字化けしなくなりました。

f:id:okazuki:20130916121412p:plain

めでたしめでたし。

Viewing all 1387 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>