ASP.NET MVC 3 seminari kokkuvõte

26.08.2010  |  Gunnar

Eile toimunud ASP.NET MVC 3 seminaril tutvustasin ASP.NET MVC 3 Preview 1 põhjal uuendusi, mis on tulemas. Neile, kes kohale ei saanud tulla, annan kiire ülevaate räägitust ja lisan juurde ühe seminaril tehtud näite ka. Et osalejatelgi huvitavam oleks, siis kande lõpust leiab ühe peatüki eksklusiivset sisu kah. Lähipäevil panen Eneta portaali üles ka ettekande slaidid ja koodinäiteid, nii et hoidke silma peal, kellel huvi on.

Peamised uuendused on järgmised:

  • DI konteinerite ja Service Locator tugi (see on küllaltki vähe dokumenteeritud teema, kuid selle leevenduseks on installeriga kaasas näiterakendus antud teemadel),
  • Razor view engine,
  • Globaalsed action filtrid,
  • Action result-id erinevate HTTP staatuse koodide määramiseks,
  • andmevahetus kontrolleriga üle ViewModel objekti,
  • JSON pöördumiste tugi kontrollerite meetodites,
  • .NET 4.0 valideerimise raamistiku tugi,
  • Uued ümbersuunamismeetodid.
  • Et tegemist on ASP.NET MVC versiooniga, mis pole RC, siis on selge, et lõplik featuuride koosseis ei ole 100% paigas ja kindlasti lisandub juurde veel palju huvitavat.

    Vedamaks välja tasemele 300 vastavat kannet, annan edasi ühe näite ka, mis seminaril tehtud sai. Teemaks siis uued action result-id ja serveri staatuse koodidega mängimine.

    HttpNotFoundResult ja HttpStatusCodeResult

    Need kaks uut action result-i võimaldavad tekitada olukorra, kus kontrolleri meetodi kutsumine lõpeb HTTP staatuse koodi muutmisega. Seni on tulnud seda teha pisut häkkide laadselt. Näiteks:

    public ActionResult Product(int id)
    {
        var model = _productModel;
        var product = model.GetProductById(id);

        if (product == null)
        {
            Response.StatusCode = 404;
            return View("Error404");
        }

        return View(product);
    }

    Nüüd saame näiteks puuduva lehe korral kasutada sellist lähenemist:

    public ActionResult Product(int id)
    {
        var model = _productModel;
        var product = model.GetProductById(id);

        if (product == null)
            return new HttpNotFoundResult();
            //return new HttpStatusCodeResult(404);
            //return HttpNotFound();

        return View(product);
    }

    Välja kommenteeritud read annavad sama tulemuse, mis return järel välja kommenteerimata rida. Pole ju erilist vahet kahe näidatud meetodi vahel, võiks öelda. Aga on. Vähemasti nende jaoks, kes teste viitsivad kirjutada ja kelle rakendused seega kvaliteedilt konkurentidele pika puuga ära panevad.

    HttpNotFoundResult kasutamine ühiktestides

    Kontrolleri meetodite testimise teeb teinekord tülikaks just see, et koos kontrolleriga tuleb mängu veebiraamistiku alumiste kihtide klasse. Selleks, et eeltoodud meetodi testida, tuli varem testides ajada kontrolleri instantsile külge ka kõik HTTP-konteksti objektid. Mulle see lähenemine väga ei meeldi, sest parem kui testid on õhukesed ja parem kui neid saab kirjutada lihtsa vaevaga – palju saab neid kokku nii või teisiti.

    Järgnevalt üks kiire näide testist, mis kontrollib eeltoodud meetodit olukorras, kus toodet ei leitud. Tegemist on ebaviisaka all-in-one meetodiga, mis päris koodis esineda ei tohiks (kuigi Eestis ma olen näinud vist kõik näited lives ära sellest, kuidas ei tohi).

    [TestMethod]
    public void ProductPageShouldReturn404IfProductNotFound()
    {
        var productId = 1;
        var product = new Product
                          {
                              Id = 2,
                              Name = "Heineken",
                              Producer = "Heineken International",
                              Amount = 0.33M,
                              Unit = "l",
                              Price = 1.7M
                          };
        var productList = new List<product> { product };

        product = null;

        var model = new Mock<productsmodel>();
        model.Setup(c => c.GetProducts())
                         .Returns(productList);
       
        model.Setup(c => c.GetProductById(productId))
                         .Returns(product)
                         .Verifiable();

        var controller = new HomeController(model.Object);
        var result = controller.Product(productId);

        model.Verify();
        Assert.IsNotNull(result);
        Assert.IsInstanceOfType(result, typeof(HttpNotFoundResult));
    }

    Suurem osa testi koodist tegeleb sellega, et asendada mudeli meetodite kutsed ära meile sobivatega. Kontrolleri enda jooksutamine ja tulemuste kontrollimine on vaid paar tühist rida. Ei mingit jamamist HTTP-konteksti objektidega.

    HttpStatusCodeResult laiendamine

    HttpNotFoundResult ja HttpStatusCodeResult on küll head, kuid samas pisut puudulikud – hetkel ei saa me koos nendega anda kaasa sisu. Näiteks vea 404 korral oleks tore, kui saaksime anda edasi ka kasutajale arusaadava väljundi.

    Mina lahendasin selle probleemi selliselt, et tegin uue klassi, mille baasiks on ViewResult. Klass ise on selline:

    public class HttpStatusCodeWithBodyResult: ViewResult
    {
        private int _statusCode;
        private string _description;
     
        public HttpStatusCodeWithBodyResult(int statusCode,
               string description = null)
            : this(null, statusCode, description)
        {
               
        }
        public HttpStatusCodeWithBodyResult(string viewName, int statusCode,
               string description = null)
        {
            _statusCode = statusCode;
            _description = description;
            ViewName = viewName;
        }
     
        public override void ExecuteResult(ControllerContext context)
        {
            var httpContext = context.HttpContext;
            var response = httpContext.Response;
     
            response.StatusCode = _statusCode;
            response.StatusDescription = _description;
               
            base.ExecuteResult(context);
        }
    }

    Ja koodis võiks seda kasutada selliselt:

    public ActionResult NotFound()
    {
        var msg = "I cannot find this resource!";
     
        // vajalik on vaade nimega NotFound.aspx või NotFound.cshtml
        var result = new HttpStatusCodeResultWithBody("NotFound", 404, msg);
        return result;
    }

    View nimega ProductError404.aspx on see, mis sisaldab kasutajale arusaadavat teksti tekkinud vea kohta.

    Kokkuvõtteks

    Kuigi aega oli seminaril vähe, sai siiski kõik oluline edasi antud. Tänastel ASP.NET MVC fännidel soovitan kindlasti kolmandama versiooniga hakata tutvust tegema, sest veel on aega selleks, et rääkida uue versiooni arengus kaasa. Vähemasti on minul selleks võimalus olemas ja kellel on uue versiooni osas soove, siis andku teada – head ideed pannakse ikka toime. Mis ettekanne järgmiseks minu poolt tuleb, ei ole veel selge. Käimas on jube kiire ja inimvaimu tõsiselt tappev periood, mis loodetavasti peatselt läbi saab. Arvatavasti ma millestki ahjusoojast jälle räägin, sest uut ja huvitavat on viimasel ajal juhtunud palju.

    Kommenteeri

    sulge
    Saada link e-postiga

    © DT 2012 | Creative Commons Attribution-Noncommercial 3.0 License | WordPress