Aplicatia este www.scurt.ro si o gasiti la adresa www.scurt.ro. Este o aplicatie de shortening service ( tinyurl si bit.ly fiind unele cunoscute deja).
Documentatia aplicatiei o gasiti la adresa http://www.scurt.ro/Home/About .
Mai intii , ce vreau sa fac cu aceasta aplicatie: Vreau sa arat ca programarea este doar baza piramidei. Si ca munca pentru o aplicatie simpla este destul de mare, in plus mai trebuie tot felul de persoane - testare,raportare, administrator de BD, SEO specialist, marketing, vinzari si altii…
Aplicatia mai are citeva chestii de facut ( de ex., paginile pentru utilizatorii inregistrati, logare,erori , add-on de IE si Firefox, SEO, etc- le gasiti in documentul http://www.scurt.ro/Docs/aplicatia%20scurt.docx )
Pentru cei care ma ajuta nu pot sa le promit nimic – decit ca vor fi mentionati printre autori –si vor avea link pus pe o pagina care trebuie definita.
Cine vrea sa ma ajute, va rog sa cititi documentul, downloadati sursele – si vorbim pe email!
Multumesc,
Andrei
Daca va place ASP.NET MVC, as fi interesat sa imi dati feedback la aceasta mini-e-carte
Am pus-o in format Word si PDF – word daca vreti sa faceti modificari la ea, pdf daca nu aveti Word
Multumiri celor care mi-au dat feedback :
Bogdan Maxim,http://www.bogdanmaxim.ro/ , pentru ca mi-a aratat greseli legate de poze/formatare si mi-a facut sugestii legate substanta cartii .
Mecu Sorin AKA Yoda, http://ronua.ro/CS/members/yoda/default.aspx - pentru aditionale sugestii legate de subiect.
Stefan Pirvu AKA Strofo , http://sharp-monkey.blogspot.com/ - pentru sugestii legate de formatare si de substanta cartii.
Alin Berce, http://alinberce.wordpress.com/ - pentru sugestii legate de formularea problematicii.
Catalin Gheorghiu AKA Mr.Smersh, http://itboard.ro/blogs/catalins_blog/, pentru poze, cod si resurse.Precum si pentru o sugestie ( nefacuta) de a utiliza FxCop si a imi corecta codul ( rusine mie!)
Andrei Rinea, http://blog.andrei.rinea.ro/ , pentru detalii legate de carte.
Gabriel Enea , http://gabrielenea.blogspot.com/ , Senior Software Developer, fondator al serviciului joobs.ro, pentru suport, review si sugestii.
Aurelian Popa, http://aurelian.ro/dasBlogCE/ , pentru continut, formatare/ si sugestii si pentru Postfata .
Timotei Dolean, http://timoteidolean.wordpress.com/, pentru sugestii legate de continut si formatare.
Tudor Turcu, http://www.turcu.name/ , pentru sugestii legate de continut.
Sau, daca vreti tiparita(si vreti sa am si eu un ce profit), atunci puteti cumpara de la Amazon :
Romana : http://www.amazon.com/Asp-Net-Tips-Tricks-Romanian/dp/1449563562/ref=sr_1_1?ie=UTF8&qid=1260851152&sr=8-1
Engleza : http://www.amazon.com/Asp-NET-MVC-Tips-Tricks-programmer/dp/144992123X/ref=sr_1_1?ie=UTF8&qid=1260851053&sr=8-1
Stiu ca ma chinuisem pina sa gasesc un control de calendar pentru ASP.NET (RJS.POPCALENDAR) -si apoi deodata am data de ASP.NET MVC – si deodata nu functiona.
Asa ca solutia a fost sa caut cu jquery – si bineinteles exista www.jqueryui.com .
Ce aveti de facut daca aveti un textbox , de ex
<input type="text" id="FromDate" name="FromDate" value="<% =ViewData.Model.data.ToString("yyyy-MM-dd") %>" />
- si vreti un mic buton linga el care sa afiseze calendarul ? Nimic mai simplu . Downloadati de la www.jqueryui.com/download jquery-ui, adaugati la proiect in folderul scripts,puneti imaginea de buton (sa ii zicem calndar.jpg) si urmatorul cod :
$(document).ready(function() { //seteaza date picker var hid = ($("#FromDate").attr("type") == "hidden"); if (!hid)//daca nu e input type = hidden
{
$("#FromDate").datepicker({ showOn: 'button', buttonImage: '/content/images/calendar.jpg’, buttonImageOnly: true , changeMonth: true, changeYear: true , dateFormat: 'yy-mm-dd'//, numberOfMonths: 2 }); }
Am avut o problema aparent minora cu ASP.NET MVC . Aveam un path de forma /client/view//client/view/http://localhost/<numevirtualdir>/client/view/<nume client>
Foarte bine si frumos – dar stiati ca nu accepta caractere ciudate in path ( de exemplu, ampersant :, A&D Servicii SRL) . Eroarea este :
This error (HTTP 400 Bad Request) means that Internet Explorer was able to connect to the web server, but the webpage could not be found because of a problem with the address.
For more information about HTTP errors, see Help.
Am cochetat cu ideea sa schimb denumirea – si sa pun codul lor – dar supriza : codul era non-numeric : A&DS …
Am inlocuit, fara sa ma gindesc prea mult, & cu & - aceeasi eroare, normal!
In cele din urma, dupa cautari amarnice( 2 ore…) pe internet, am dat de un fisier .reg cu 2 rinduri – sper sa va fie de folos :
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET] "VerificationCompatibility"=dword:00000001
Destul de tirziu mi-am dat seama de beneficiile aduse de un Mock – dar mai bine mai tirziu decit niciodata …
Ma gindeam ca niciodata nu o sa il folosesc – ca ajunge sa verific BLL cu unit test(NUNIT/VS Test) , site-ul Web cu NUnit ASP/WATI(N|R) / Selenium , Windows Forms cu NUnitForms si nu o sa am nevoie de Mock.
Adevarul este ca da, nu as avea nevoie de Mock … decit daca as vrea sa verific mai repede unele date, fara sa ating BD.De exemplu, pot sa verific controller-ele fara sa am nevoie sa instantiez HttpContext si BD. Sa zicem ca am un controller care are o actiune ce doar exporta un fisier Word– bazat pe un template. Codul din fisier arata cam asa :
public ActionResult ExportDate(string id) {
IDateExport fe = ObjectFactory.GetInstance<IDateExport>(); fe.id = id;
export exp = new export(Server.MapPath("~/bin/Templates"));
FileContentResult fcr = new FileContentResult(exp.Export(fe), "application/ms-word"); fcr.FileDownloadName = fe.Number + ".doc";
return fcr;
}
Daca as vrea sa verific rapid metoda aceasta ar trebui sa nu ating baza de date si sa am pun un rezultat in loc de Server.MapPath ?
Se vede clar ca deja folosesc StructureMap, deci nu ar fi o problema cu gasitul a niste date fake. Dar pentru Server.MapPath intervine stralucit Mock.
Am preluat de la Hanselmann MVC Mock Helpers ,iar codul de test arata cam asa :
exportController i = new exportController(); MockRepository mocks = new MockRepository(); using (mocks.Record()) { //MvcMockHelpers.SetFakeControllerContext(mocks, i); mocks.SetFakeControllerContext(i); SetupResult.For(i.ControllerContext.HttpContext.Server.MapPath(null)).IgnoreArguments().Return(@"c:\programs\templates"); // cod pentru chemarea Server.MapPath mocks.ReplayAll(); } using (mocks.Playback()) { ObjectFactory.Initialize(x => { x.ForRequestedType<IExport>().TheDefaultIsConcreteType<FactFind>();// FactFind nu atinge BD }); FileContentResult fcr = i.exportdate("865", "A") as FileContentResult; fcr.ShouldNotBeNull(); fcr.FileContents.Length.ShouldBeGreaterThan(0);//TODO : Verifica si continutul }
Voi ce alte frameworkuri/tools-uri folositi ?
Pentru cei care se mai chinuie ca , desi au configurat log4net corect, in asp.net mvc nu logheaza nimic…
Inceput : pus un log4net.config, pus in global.asax in start Application :
System.IO.FileInfo s=new System.IO.FileInfo(Server.MapPath("log4net.config")); log4net.Config.XmlConfigurator.ConfigureAndWatch(s);
pus un un controller in homecontroller de tipul :
public ActionResult error() { return View("Error", new HandleErrorInfo(new ArgumentException("asd"), "home", "error" + _logger.IsErrorEnabled)); }
Cind browsam http://localhost/site/home/error , imi afisa “error” FALSE
Cind faceam debug din VS ,imi afisa “error” TRUE .
Am innebunit cautind rezolvarea … si, dupa mai multe incercari nereusite, m-am hotarit sa fac debug.
In web.config sub <configuration> :
<appSettings> <add key="log4net.Internal.Debug" value="true"/> </appSettings>
<system.diagnostics> <trace autoflush="true"> <listeners> <add name="textWriterTraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="<cale catre site>\log\log4net.txt" />
<!-- vedeti sa aveti drept de scriere pentru user-ul de aspnet-->
</listeners>
</trace>
</system.diagnostics>
<system.web> <trace enabled="true"/>
Si mi-a aparut :
log4net: XmlConfigurator: config file [<site>\home\log4net.config] not found.
Asa ca am schimbat :
System.IO.FileInfo s=new System.IO.FileInfo(Server.MapPath("log4net.config")); cu
System.IO.FileInfo s=new System.IO.FileInfo(Server.MapPath("~/log4net.config"));
SI GATA!
Am avut de facut o aplicatie cu ASP.NET MVC - si bineinteles, cu un grid ce lista niste vinzari si cu total.
Asta e ceea ce mi-a pus probleme : totalul … Asa incit, dupa ce am studiat grid-ul de la ASP.NET MVC Contrib , a trebuit sa il extind. Si nu a fost foarte greu. Mai intii , practica - sintaxa e asemanatoare, doar ca adaug o functie pentru footer :
<% =Html.HtmlGridFooter<Lines>(ViewData.Model.Lines, (x) => { decimal total = 0; foreach (var s in x) { total += s.Total; }; return "<tr><td colspan=1 align=right>Total</td><td colspan=1>"+ total.ToString("#.00")+"</td></tr>"; }
) si de aici incepe grid-ul obisnuit.
Teoria : a trebuit sa extind HtmlTableGridRenderer si sa il atasez de grid …Probabil ca o sa fie nevoie sa am , odata, doi grid renderer?
Cod :
public class HtmlGridFooter<T> : Grid<T> where T : class { public HtmlGridFooter(IEnumerable<T> dataSource, TextWriter writer, ViewContext context) : base(dataSource, writer, context) { } public Func<IEnumerable<T>, string> footer { set { this.RenderUsing(new FooterHtmlGrid<T>() { actions = base.DataSource, footer = value }); } }
} public class FooterHtmlGrid<T> : HtmlTableGridRenderer<T> where T : class { public IEnumerable<T> actions; public Func<IEnumerable<T>,string > footer; protected override void RenderGridEnd(bool isEmpty) { if (footer != null) { base.RenderText(footer(actions)); } base.RenderGridEnd(isEmpty); } }
si intr-o clasa statica ar trebui pus:
public static IGrid<T> HtmlGridFooter<T>(this HtmlHelper helper, IEnumerable<T> dataSource, Func<IEnumerable<T>, string> footer) where T : class { HtmlGridFooter<T> g = new HtmlGridFooter<T>(dataSource, helper.ViewContext.HttpContext.Response.Output, helper.ViewContext); g.footer = footer; return g; }
Ca in ASP.NET MVC Best Practices( aici, aici, aici, aici si aici ) am pus o metoda in Controller care sa faca legatura automat cu acea clasa ce trebuie salvata:
[AcceptVerbs(HttpVerbs.Post)] [Authorize()] public ActionResult Index([Bind(Exclude = "IDAlert,IDPerson", Prefix = "")]CV_Alerte c) {}
Insa am avut o problema subtila : CV_Alerte are un membru Valoare de tipul double care este mapat la un textbox. Ce se intimpla daca trimit xxx ?
La o cautare rapida pe net, gasesc raspunsul : Verifica ModelState.IsValid . OK, si acum cum iau eroarea ? Nu am gasit pe net, asa ca, dupa o investigare rapida a surselor, am gasit metoda:
if (!ModelState.IsValid) { foreach (var s in ModelState.Keys) { if (!ModelState.IsValidField(s)) { ModelState.AddModelError(s,"aveti o eroare la setarea " + s + "--" + ModelState[s].Value.AttemptedValue); } } return View(); }
Ar fi trebuit sa o faca ei!
Ca referinta la ASP.NET Best Practices:
http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx http://weblogs.asp.net/rashid/archive/2009/04/03/asp-net-mvc-best-practices-part-2.aspx http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/04/24/how-we-do-mvc.aspx http://codeclimber.net.nz/archive/2009/04/17/how-to-improve-the-performances-of-asp.net-mvc-web-applications.aspx http://blog.maartenballiauw.be/post/2009/05/06/More-ASPNET-MVC-Best-Practices.aspx
si,bineinteles, eu
Disclaimer : Acest post se refera la un website obisnuit, la care nu ai acces la configurarea de pe server(de ex., nu ai acces la IIS Compression) si trebuie sa ti le faci singur
Marota mea favorita, www.infovalutar.ro, se incarca destul de greu prima oara. Asa incit a trebuit sa ii fac o optimizare. Site-ul fiind facut cu ASP.NET MVC, prima optimizare chioara am facut-o cu [OutputCache] pe controller. Asta cacheuia si pagina, si datele …tot. Ca sa vad cum cachuieste, am gasit un Html.Substitution cu care pot sa afisez chestii ne=cache-uite (modificat un pic, ca poate am nevoie sa scriu stringul EXACT asa cum este …):
public static object Substitute(this HtmlHelper html, MvcCacheCallback cb, bool Encode) { if (Encode) { html.ViewContext.HttpContext.Response.WriteSubstitution( c => HttpUtility.HtmlEncode( cb(new HttpContextWrapper(c)) ));
} else { html.ViewContext.HttpContext.Response.WriteSubstitution( c => ( cb(new HttpContextWrapper(c)) ));
} return null; }
OK, apoi am inceput sa ma gindesc la optimizari … Mai intii imaginile, apoi css-urile + jscript, apoi redirect-urile . Asa ca am zis ca cel mai bine este sa incerc cu un tool – si primul ales este Fiddler. Asa ca am vazut redirecturi (301)la greu .De ce le aveam ? pentru ca aveam probleme la controlere pentru uppercase/lowercase la argumente si m-am decis ca toate sa fie cu lowercase , asa incit pusesem in global.asax
protected void Application_BeginRequest(Object sender, EventArgs e) { // If upper case letters are found in the URL, redirect to lower case URL. if (Regex.IsMatch(HttpContext.Current.Request.Url.ToString(), @"[A-Z]") == true) { string LowercaseURL = HttpContext.Current.Request.Url.ToString().ToLower();
Response.Clear(); Response.Status = "301 Moved Permanently"; Response.AddHeader("Location", LowercaseURL); Response.End(); } }
Asa ca am intervenit in site si am schimbat ca toate sa fie cu litere mici (un .ToLower() la linkuri a ajuns)
Dar am revenit la problema initiala: mai aveam nevoie sa fie cache-uite imaginile,css-urile si jscripturile. E adevarat, ma puteam uita in Fiddler(click pe fisier=>inspectors )
sa vad care e cache-uita, care e zip-uita – dar aveam nevoie de un tool general. Asa ca , pentru mine , combinatia ideala a ajuns : Firefox + Firebug + Yahoo Slow + Google Page Speed. OK,daca vi le-ati instalat pe toate atunci puteti incepe cu yahoo Slow – si, ca sa ma dau bun iata cum arata la mine:
Va rog sa observati ca am Grade A pentru “Small Site or Blog” . OK, ceea ce recomanda Yahoo Slow si nu faceam era:
1 si 2 sunt relativ usor – mai modifica site master-ul si gata.
3.Cum facem Compress components with Gzip ? Am cautat rapid – si am gasit, in final, asta GZip and Deflate Compression Filter for ASP.Net MVC . Am pus-o, mergea bine pe masina mea, dar cum am pus-o in productie , cum a dat eroarea asta . Asa ca a trebuit sa renunt la OutputCache – si sa fac caching pe ASP.NET Cache – dar asta doar la datele din BD .Acum mergea perfect! Dovada : nu a mai aparut pagina la Yahoo Slow - iar , inspectata cu fiddler => inspector , a aparut Gzip.
4.OK, acum era problema de optimizare a imaginilor – mai exact, vroiam ca imaginile sa ramine in cache-ul browser-ului, astfel incit sa nu se mai downloadeze inca o data. Pentru asta trebuia sa setez expiration la image -dar cum, daca nu am acces la server ? Ca de obicei, se rezolva cu o indirectare: Sa zicem ca imaginile sunt in folder-ul flags. Atunci il pus sa treaca printr-un controller:
public static void RegisterRoutes(RouteCollection routes) { routes.MapRoute("flags", "flags/{id}.ashx", new { controller = "imagini", action = "flags" });
//alte date
Iar fiecare imagine se va prelungi cu un ashx ( adica .gif.ashx) :
<img width="30" height="20" src="/<% ="flags/" + curLoop.IDMoneda.ToLower() + ".gif.ashx"%>" />
In controller-ul respectiv pe actiunea flags, redam imaginea :
Response.Cache.SetExpires(DateTime.Now.AddDays(300));// Response.Cache.SetCacheability(HttpCacheability.Public); Response.Cache.SetValidUntilExpires(false); Response.AddHeader("content-disposition", "inline; filename=" + filename);
Response.WriteFile(file); OK, acum iarasi Fiddler si presto : imaginile erau cache-uite aproximativ 1 an. Dar cum sa fac cu Jscriptul ca sa fie si compresat si cache-uit ? Pai – acelasi lucru – sa treaca printr-un Controller si sa ii aplic Gzip prin clasa CompressFilter. Aici am avut cea mai mare problema : de acasa imi dadea ca js e compresat – la servici ca nu. Innebunisem – si totul s-a rezolvat cu //proxy servers in between may cache Response.AppendHeader("Vary", "Accept-Encoding"); Bun, deja ma miscam mai usor in sensul ca pagina, de la citiva bun kb ajunsese la a doua iteratie la < 10 (ma rog, cu reclame < 15) Daca apasati pe Statistics o sa vedeti 2 grafice : una de la prima incarcare si una de la a doua incarcare (in care nu se mai incarca cache-ul de la prima)– Daca numarul de Http Requests si numarul de Kb este acelasi – atunci aveti o problema. La mine este 48 / 6 Requests – cu 84 / 13 Kb. Daca ati facut pina aici - e super! Acum sa mai aplicam doar Google Page Speed – acesta este doar cireasa de pe tort Cu el am mai optimizat din imagini , m-am uitat ca puteam optimiza prin minify “There is 173.8kB worth of JavaScript. Minifying could save 4.7kB (2.7% reduction).” – ma rog, doar pentru primii veniti – ceilalti au oricum cache-ul… ca ar trebui sa fac “This page makes 43 parallelizable requests to infovalutar.ro. Increase download parallelization by distributing these requests across multiple hostnames:” – mda, si de unde bani ? Si yahoo vorbeste de CDN-uri
Response.WriteFile(file);
OK, acum iarasi Fiddler si presto : imaginile erau cache-uite aproximativ 1 an.
Dar cum sa fac cu Jscriptul ca sa fie si compresat si cache-uit ? Pai – acelasi lucru – sa treaca printr-un Controller si sa ii aplic Gzip prin clasa CompressFilter.
Aici am avut cea mai mare problema : de acasa imi dadea ca js e compresat – la servici ca nu. Innebunisem – si totul s-a rezolvat cu
//proxy servers in between may cache Response.AppendHeader("Vary", "Accept-Encoding");
Bun, deja ma miscam mai usor in sensul ca pagina, de la citiva bun kb ajunsese la a doua iteratie la < 10 (ma rog, cu reclame < 15)
Daca apasati pe Statistics o sa vedeti 2 grafice : una de la prima incarcare si una de la a doua incarcare (in care nu se mai incarca cache-ul de la prima)– Daca numarul de Http Requests si numarul de Kb este acelasi – atunci aveti o problema. La mine este 48 / 6 Requests – cu 84 / 13 Kb.
Daca ati facut pina aici - e super! Acum sa mai aplicam doar Google Page Speed – acesta este doar cireasa de pe tort
Cu el am mai optimizat din imagini , m-am uitat ca
OK, ultimul tool de care voiam sa va vorbesc este Search Engine Optimization Toolkit. Este o scula extraordinara pentru incepatorii ca mine, se integreaza de minune in VISTA . Il rulati odata pe site-ul vostru(din IIS,vedeti Scott http://weblogs.asp.net/scottgu/archive/2009/06/03/iis-search-engine-optimization-toolkit.aspx ) , puteti creea robots.txt, sitemap si vedea multe altele. Oricum, postul lui Scott http://weblogs.asp.net/scottgu/archive/2009/06/03/iis-search-engine-optimization-toolkit.aspx spune tot – si face analiza chiar pe site-ul propriu! Nu spun pe www.infovalutar.ro cit mi-a gasit!
Oricum, daca faceti site-uri, e bine de avut in trusa de dezvoltator!
Daca puneti pe controller HandleError si vreti pe o metoda sa interceptati HandleError pentru o anumita exceptie, nu uitati sa puneti order=0 pentru HandleError de pe controller.
[InfovalNew.HandleErrorAndLog(Order=0)] public class istoricController : Controller
[InfovalNew.HandleErrorAndLog(View = "invaliddate",ExceptionType = typeof(infoObj.InvalidDateTime))] public string valoarebnr(string year, string month, string day,string idmoneda) {}
Nu eram multumit de vechiul sitemap de la ASP.NET – din singurul motiv ca nu e dinamic - adica nu tine seama ca poate exista Categorie\Produs\{id}\edit.
Ca omul puturos , am cautat pe google si am gasit pe codeplex http://mvcsitemap.codeplex.com/
Citeva observatii :
Succes!
Zilele(noptile?) acestea, cum am spus de atitea ori, am trecut pet-project, www.infovalutar.ro la ASP.NET MVC.
Si ma gindeam cum sa ii imbunatatesc timpul de afisare. OK, yahoo slow pentru inceput imi spunea ca nu am expires header la imagini. Stiam ca exista in IIS -dar cum le setez la hosting? Dau telefon, amabil, ii spun unde sa faca – dar … ceva nu a mers. Si au ramas ca la inceput.
Asa incit le-am mapat o extensie proprie, ashx, si le-am pus sa fie interceptate de un handler si le-am setat cam ca aici
OK –teoretic asta cam ar trebui sa o faca oricine.
Ce parere aveti de un mini-site de best practices , gen wiki, pe care sa il tinem updatat la zi cu ce intilnim noi ca developeri ?
Cum am spus, am trecut www.infovalutar.ro de la asp.net 1.1 la ASP.NET MVC.Trecerea nu a fost usoara, si inca sunt citeva lucruri de facut.
Totusi una din probleme care mi-a dat de furca a fost ca ChartImage , la refresh, nu se mai afisa. Foloseam asta la afisarea grafica a datelor cursurilor, de ex. http://infovalutar.ro/bnr/graphic/usd
Bun … problema era ca stergea fisierul png generat. Am pus “deleteAfterServicing “ la false * si o sa le sterg in momentul in care generez cursurile.
Totusi, mai aveam o problema . Daca accesam site-ul cu Firefox si dadeam refresh, se vedea. Dar aceeasi pagina , cu IE 7 , nu mai afisa - desi in codul HTML generat codul de la AXD era ACELASI, IMAGINEA era pe hard …
Dupa mai multe cautari am dat de pagina asta, http://blogs.msdn.com/deliant/archive/2008/12/02/managing-chart-generated-images-with-chart-image-handler.aspx care are TOATE setarile si ma dat de privateImages … L-am pus la false si gata!
Rezumat : pentru a folosi ChartImage cu succes cu IIS 7 aveti nevoie de 3 setari:
<appSettings> <add key="ChartImageHandler" value="storage=file;privateImages=false;timeout=600;dir=….;deleteAfterServicing=false;" /> </appSettings>
A doua in httphandlers
<httpHandlers><add path="ChartImg.axd" verb="GET,HEAD,POST" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false" />
A treia in handlers
<add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD,POST" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
Si, bineinteles, daca hostingul nu a instalat inca controalele, sa puneti din references System.Drawing si System.Web.DataVisualization “Copy local” la true – ca sa le aveti in bin
A fost primul live meeting al meu - am vorbit despre ASP.NET MVC. A fost destul de ciudat sa vorbesc la pereti si sa nu aud pe nimeni … dar sper ca a fost ok dupa citeva aaa-uri. Prezentarea a durat 50 de minute si am vorbit despre:
Multumesc lui Petru pentru oportunitate si sprijin tehnic/material/anunt
Inregistrarea o gasiti la http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032408740&EventCategory=5&culture=ro-RO&CountryCode=RO iar prezentarea o gasiti aici http://serviciipeweb.ro/iafblog/content/binary/ASPNETMVC.pdf.zip
Va astept probleme / sugestii / reclamatii / comentarii …
(Oh – si asta e un motiv pentru care tutorialul de .NET 3.5 nu a mai continuat … dar promit sa continui - dupa ce imi trag rasuflarea…)
Dupa cum a scris Petru aici si aici , o sa tin o prezentare LiveMeeting ( trebuie sa il instalati!) despre marota mea – www.infovalutar.ro portat la ASP.NET MVC
O sa aiba tips and tricks si problemele uzuale de care m-am lovit.
Va astept aici http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032408739&EventCategory=4&culture=ro-RO&CountryCode=RO
Aseara am inceput sa trec infovalutar pe Asp.NET MVC.Si aveam 2 probleme :
1. degeaba ii dadeam Home/Index/3 ca in controller-ul
public class HomeController : Controller
public ActionResult Index(string Banca)
ViewData.Model = new CurrencyList();
ViewData["Bank"] = Banca;
return View("Index");
Nu vroia sa imi ia id-ul(parametrul Banca era null) si gata, indiferent cum ii dadeam eu Home/Index/BNR sau Home sau orice altceva –desi trecea prin procedura.
M-am gindit sa dau vina pe Asp.NET MVC, dar , fiind un framework folosit de atitia, nu ma gindeam ca tocmai eu am un caz deosebit …Si citisem ca pe IIS integrated NU trebuie sa ii faci modificari …
2. Cind incerca sa se conecteze la Sql Server, imi dadea “login failed for user …”
Am incercat sa refac login-ul , sa schimb parola, ce nu am incercat …
Asa ca m-am dus la culcare si am revenit cu sentimente mai bune de dimineata.
Rezolvari :
1. M-am dus sa ma uit cum e inregistrat routing-ul in global.asax.Cum sa fie , obisnuit:
routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "BNR" } // Parameter defaults );
Si mi-a cazut fisa : parametrul de la functia index nu se cheama cum vrea el, ci cum vrea MVC – adica id
public ActionResult Index(string id) fata de public ActionResult Index(string Banca) Naspa! Mi-aduce aminte de Java, cind numele clasei = numele fisierului !
2. Am incercat , in disperare , sa ma conectez si de pe Sql Server Management Console – acelasi mesaj : “Login Failed” . In disperare, ma conectez cu credentialele de Windows si ma uit in log-urile de la SQL Server – Management/Sql Server Logs - si acolo mi-a zis ca nu se poate ca nu este configurat in mixed mode …
Ce sa mai zic ? Schimb, dau restart la Sql, merge!
Sfat catre mine : Daca nu iti iese , du-te si te culca sau apuca-te de altceva. Revii cu mintea odihnita dupa aceea!
Theme design by Jelle Druyts
Pick a theme: BlogXP business calmBlue Candid Blue dasBlog dasblogger DirectionalRedux Discreet Blog Blue Elegante essence Just Html Mono Movable Radio Blue Movable Radio Heat orangeCream Portal Project84 Project84Grass Slate Tricoleur