Sqlite i web application

W końcu udało mi się znaleźć chwilę na utworzenie projektu i połączenie się z baza Sqlite. Do czego mi przyda się ta baza ?

  • szybka w przygotowaniu, nie wymaga yinstalowania serwera
  • w sam raz do szybkich, krótkich projektów
  • dobra alternatywa na czas developmentu zanim podłączymy się do głównej bazy

Instalacja pakietu Sqlite:

Install-Package System.Data.Sqlite

Tworzymy bazę danych. Ja zrobiłem to przy użyciu Sqlite Administrator. Po kilku problemach z tymże oprogramowaniem polecam jednak SqlliteStudio (tym bardziej że tworzone przez Polaka)

Utworzyłem baze o nazwie MyDb i dodałem jedną tabelę o nazwie Player.
Sqlite table in database

Wstawiłem także jeden rekord do bazy:

Insert into Player (FirstName, LastName, Position) VALUES ('Lukasz', 'Kuklis', 'Attacker')

Nastepnie update connection stringa z nazwa pliku naszej bazy danych i odpowiednim dla Sqlite providerem.

<add name="FootballContext" connectionString="Data Source=|DataDirectory|MyDb.sqlite;" providerName="System.Data.SQLite.EF6" />

Aktualizujemy zawartość DbProviderFactories do poniższego stanu:

<remove invariant="System.Data.SQLite" />
<add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
<remove invariant="System.Data.SQLite.EF6" />
<add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".Net Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />

Sprawdzamy czy providers wygląda jak poniżej:

<providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
</providers>

Dodałem klasę domenowa odwzorowująca utworzoną tabele w bazie danych

public class Player
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Position { get; set; }
}

oraz klasę kontekstu bazy danych

public class FootballContext : DbContext
{
    public FootballContext() : base("name=FootballContext") { }
    
    public virtual DbSet<Player> Player { get; set; }
}

Na koniec pobranie danych z bazy oraz przekazanie obiektu do html

IList<Player> player;
using (var db = new FootballContext())
{
    player = db.Player.ToList();
}

return View(player.First());

Home Page   My ASP.NET Application

Klasa dla aktywnego elementu menu

Prosta sprawa – chcemy mieć zawsze zaznaczony element menu dla strony która aktualnie wyświetlamy.
Proste rozwiązanie – Helper, który będzie przypisywał naszą klasę “aktywności” do elementu, którego controller/action będzie się pokrywał z aktualnymi danymi z ViewContext.RouteData.

 public static MvcHtmlString MenuActionLink(this HtmlHelper htmlHelper, string name, string action, string controllerName, object routeValues, string activeClassName = null, IDictionary<string, object> htmlAttributes = null)
        {
            var url = new UrlHelper(htmlHelper.ViewContext.RequestContext);
            var anchor = new TagBuilder("a");
            anchor.MergeAttribute("href", url.Action(action, controllerName, routeValues));

            var routeData = htmlHelper.ViewContext.RouteData;
            var currentAction = routeData.GetRequiredString("action");
            var currentController = routeData.GetRequiredString("controller");

            if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) && string.Equals(currentController, controllerName, StringComparison.OrdinalIgnoreCase))
            {
                anchor.MergeAttribute("class", activeClassName ?? "active");
            }

            if (htmlAttributes != null)
            {
                foreach (var htmlAttribute in htmlAttributes)
                {
                    anchor.MergeAttribute(htmlAttribute.Key, htmlAttribute.Value.ToString());
                }
            }
            
            anchor.InnerHtml = name;

            return MvcHtmlString.Create(anchor.ToString(TagRenderMode.Normal));
        }

Orchard Multitenancy Themes

Stawianie tenantów w Orchardzie i przypisywanie specyficznych tematów dla danego tenanta ma jedną wadę. Nie można włączyć tego procesu automatycznego konfigurowania Orcharda. Jest to proces całkowicie manualny. Można jedynie wejść do opcji zarządzania tenantami i zaznaczyć, które tematy chcemy aby były dostępne dla konkretnego tenanta. Druga opcja to edycja pliku settings.txt.
Jeżeli chcemy dołączyć możliwość automatycznego ustawiania tematów dla tenantów potrzebujemy polecenia w konsoli Orcharda. Dlatego nie pozostaje nic innego jak utworzyć swój własny moduł z rozszerzeniem możliwości konsoli Orcharda.

Dodatkową komendę dodajemy tworząc nową klasę dziedziczącą z Orchard.Commands.DefaultOrchardCommandHandler.
Sam proces dodawania i konfigurowania nowej komendy Orcharda opisany jest tutaj
Po utworzeniu nowej metody i wstrzyknięciu serwisu tenantów, pozostaje nam już tylko wykonać update tenanta/ów z listą id (id – nie nameów) wybranych tematów.
Całość modułu dostępna jest na GitHubie pod tym linkiem.

IE IFrame i PDF

Internet Explorer ma zadziwiająca moc, dzieki której rosną nasze umiejętności kombinowania i tworzenia przeróżnych workaroundów. Ostatnio poziom adrenaliny podniósł mi feature przeglądarki Microsoftu w którym wyświetlanie plików pdf przez plugin Adobe jest nadrzędne jeśli chodzi o kolejność wyświetlania warstw.

Problem przedstawia się tak:

<style type="text/css">
	.box {
		width: 400px;
		height: 300px;
		background-color: #212121;
		position: absolute;
		z-index: 2;
	}
	iframe {
		width:100%;
		z-index: 1;
	}
	</style>

     <div class="box"></div>
     <iframe src="http://download.fds-ncom.nokia.com/supportFiles/phones/files/guides/Nokia_E51_UG_pl.pdf"></iframe>

IE IFrame Bug

Niestety w żaden cywilizowany sposób nie da się “przeskoczyć” pliku pdf. Jedyną możliwością jest oszukanie IE i podstawienie pod element który chcemy by był nadrzędny względem iframe drugiego pustego elementu iframe.

<style type="text/css">
	.box {
		width: 400px;
		height: 300px;
		background-color: #212121;
		position: absolute;
		z-index: 2;
	}
	.iframe {
		width:100%;
		z-index: 1;
	}
	.fake-iframe {
		position: absolute;
		width: 100%;
		height: 100%;
	}
	</style>

        <div class="box">
	    <iframe src="about:blank" class="fake-iframe"></iframe>
	</div>
	<iframe class="iframe" src="http://download.fds-ncom.nokia.com/supportFiles/phones/files/guides/Nokia_E51_UG_pl.pdf"></iframe>

Dostając porządany efekt:
IE IFrame bug fixed