Moje pytanie jest podobne do tego:
Tyle że chcę pozostać przy własnym pakiecie MVC, jeśli mogę. Mam awarię mózgu, próbując dowiedzieć się, jaki jest prawidłowy wzorzec określania pakietów stylów, takich jak samodzielne zestawy css i zestawy obrazów, takie jak interfejs użytkownika jQuery.
Mam typową strukturę witryny MVC, /Content/css/
która zawiera mój podstawowy CSS, taki jak styles.css
. W tym folderze css mam również podfoldery, takie jak /jquery-ui
zawierający plik CSS plus /images
folder. Ścieżki obrazów w CSS interfejsu jQuery są względne w stosunku do tego folderu i nie chcę z nimi zadzierać.
Jak rozumiem, kiedy określam StyleBundle
, muszę podać ścieżkę wirtualną, która nie pasuje również do prawdziwej ścieżki treści, ponieważ (zakładając, że ignoruję trasy do Treści) IIS spróbuje następnie rozwiązać tę ścieżkę jako plik fizyczny. Więc określam:
bundles.Add(new StyleBundle("~/Content/styles/jquery-ui")
.Include("~/Content/css/jquery-ui/*.css"));
renderowane przy użyciu:
@Styles.Render("~/Content/styles/jquery-ui")
Widzę prośbę wychodzącą na:
http://localhost/MySite/Content/styles/jquery-ui?v=nL_6HPFtzoqrts9nwrtjq0VQFYnhMjY5EopXsK8cxmg1
To zwraca poprawną, zminimalizowaną odpowiedź CSS. Ale potem przeglądarka wysyła żądanie względnie połączonego obrazu jako:
http://localhost/MySite/Content/styles/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
Co jest 404
.
Rozumiem, że ostatnia część mojego adresu URL jquery-ui
to adres URL bez rozszerzenia, moduł obsługi mojego pakietu, więc mogę zrozumieć, dlaczego względne żądanie obrazu jest po prostu /styles/images/
.
Więc moje pytanie brzmi: jaki jest właściwy sposób radzenia sobie z tą sytuacją?
źródło
Odpowiedzi:
Zgodnie z tym wątkiem dotyczącym pakietowania css MVC4 i odwołań do obrazów , jeśli pakiet zostanie zdefiniowany jako:
Jeśli pakiet zostanie zdefiniowany na tej samej ścieżce, co pliki źródłowe, które go utworzyły, względne ścieżki obrazu będą nadal działać. Ostatnia część ścieżki pakietu jest naprawdę
file name
dla tego konkretnego pakietu (tzn./bundle
Może to być dowolna nazwa).Działa to tylko wtedy, gdy łączysz razem CSS z tego samego folderu (co moim zdaniem ma sens z perspektywy łączenia).
Aktualizacja
Zgodnie z komentarzem poniżej autorstwa @Hao Kung, alternatywnie można to teraz osiągnąć poprzez zastosowanie
CssRewriteUrlTransformation
( Zmień względne odwołania do adresów URL do plików CSS w pakiecie ).UWAGA: Nie potwierdziłem komentarzy dotyczących problemów z przepisywaniem do absolutnych ścieżek w katalogu wirtualnym, więc może to nie działać dla wszystkich (?).
źródło
Rozwiązanie Grinn / ThePirat działa dobrze.
Nie podobało mi się, że nowa metoda zawierała pakiet w pakiecie i że tworzyła pliki tymczasowe w katalogu zawartości. (skończyło się na odprawie, wdrożeniu, usługa się nie uruchomi!)
Dlatego podążając za projektem sprzedaży wiązanej, zdecydowałem się wykonać zasadniczo ten sam kod, ale w implementacji IBundleTransform ::
A potem zapakowałem to w pakiet: Implemetation:
Przykładowe użycie:
Oto moja metoda rozszerzenia dla RelativeFromAbsolutePath:
źródło
relativeToCSS
przed wywołaniemPath.GetFullPath()
.Lepiej jeszcze (IMHO) zaimplementuj niestandardowy pakiet, który naprawia ścieżki obrazu. Napisałem jeden dla mojej aplikacji.
...
Aby z niego skorzystać:
...zamiast...
To, co robi (gdy nie jest w trybie debugowania), szuka
url(<something>)
i zamienia je naurl(<absolute\path\to\something>)
. Napisałem tę rzecz około 10 sekund temu, więc może potrzebować trochę poprawek. Wziąłem pod uwagę w pełni kwalifikowane adresy URL i baseURI DataURI, upewniając się, że w ścieżce URL nie ma dwukropków (:). W naszym środowisku obrazy zwykle znajdują się w tym samym folderze, co ich pliki css, ale przetestowałem je zarówno z folderami nadrzędnymi (url(../someFile.png)
), jak i podrzędnymi (url(someFolder/someFile.png
).źródło
Nie trzeba określać transformacji ani mieć zwariowanych ścieżek podkatalogów. Po wielu problemach wyodrębniłem go z tej „prostej” reguły (czy to błąd?) ...
Jeśli ścieżka pakietu nie zaczyna się od względnego katalogu głównego uwzględnionych elementów, katalog główny aplikacji internetowej nie zostanie uwzględniony.
Brzmi dla mnie bardziej jak błąd, ale w każdym razie tak to naprawiasz w obecnej wersji .NET 4.51. Być może inne odpowiedzi były konieczne na starszych kompilacjach ASP.NET, nie mogę powiedzieć, że nie mam czasu na retrospektywne testowanie tego wszystkiego.
Aby to wyjaśnić, oto przykład:
Mam te pliki ...
Następnie skonfiguruj pakiet jak ...
I renderuj to jak ...
I dostańmy „zachowanie” (błąd), same pliki CSS mają katalog główny aplikacji (np. „Http: // localhost: 1234 / MySite / Content / Site.css”), ale obraz CSS na początku ”/ Content / Images / ... ”lub„ / Images / ... ”w zależności od tego, czy dodam transformację, czy nie.
Próbowałem nawet utworzyć folder „Pakiety”, aby sprawdzić, czy ma to związek z istniejącą ścieżką, czy nie, ale to nic nie zmieniło. Rozwiązaniem problemu jest tak naprawdę wymóg, że nazwa pakietu musi zaczynać się od katalogu głównego ścieżki.
Oznacza to, że ten przykład został naprawiony przez zarejestrowanie i renderowanie ścieżki pakietu jak ...
Oczywiście można powiedzieć, że to RTFM, ale jestem pewien, że ja i inni wybraliśmy tę ścieżkę „~ / Bundles / ...” z domyślnego szablonu lub gdzieś w dokumentacji na stronie MSDN lub ASP.NET, lub natknąłem się na to, ponieważ w rzeczywistości jest to dość logiczna nazwa wirtualnej ścieżki i sensowne jest wybranie takich wirtualnych ścieżek, które nie kolidują z prawdziwymi katalogami.
W każdym razie tak właśnie jest. Microsoft nie widzi błędu. Nie zgadzam się z tym, albo powinno działać zgodnie z oczekiwaniami, albo powinien zostać zgłoszony wyjątek, lub dodatkowe zastąpienie dodawania ścieżki pakietu, która decyduje się na włączenie katalogu głównego aplikacji, czy też nie. Nie mogę sobie wyobrazić, dlaczego nikt nie chciałby uwzględniać katalogu głównego aplikacji, gdy taki był (zwykle, chyba że zainstalowałeś witrynę z aliasem DNS / domyślnym katalogiem głównym witryny). Więc tak naprawdę powinno to być ustawienie domyślne.
źródło
Odkryłem, że CssRewriteUrlTransform nie działa, jeśli odwołujesz się do
*.css
pliku i masz powiązany*.min.css
plik w tym samym folderze.Aby to naprawić, usuń
*.min.css
plik lub odwołaj się bezpośrednio do niego w pakiecie:Po wykonaniu tej czynności adresy URL zostaną poprawnie przekształcone, a obrazy powinny zostać poprawnie rozwiązane.
źródło
Być może jestem stronniczy, ale bardzo podoba mi się moje rozwiązanie, ponieważ nie wykonuje żadnych transformacji, wyrażeń regularnych itp. I ma najmniejszą ilość kodu :)
Działa to w przypadku witryny hostowanej jako katalog wirtualny w witrynie sieci Web IIS i jako witryna główna w usługach IIS
Więc stworzyłem Implentację w postaci
IItemTransform
enkapsulowanejCssRewriteUrlTransform
i użyłemVirtualPathUtility
do naprawy ścieżki i wywołania istniejącego kodu:Wydaje mi się, że działa dobrze?
źródło
Chociaż odpowiedź Chrisa Baxtera pomaga w rozwiązaniu pierwotnego problemu, w moim przypadku nie działa, gdy aplikacja jest hostowana w katalogu wirtualnym . Po zbadaniu opcji skończyłem z rozwiązaniem DIY.
ProperStyleBundle
klasa zawiera kod zapożyczony z oryginału,CssRewriteUrlTransform
aby poprawnie przekształcić ścieżki względne w katalogu wirtualnym. Zgłasza także, jeśli plik nie istnieje i zapobiega zmianie kolejności plików w pakiecie (kod pobrany zBetterStyleBundle
).Używaj go jak
StyleBundle
:źródło
Od wersji 1.1.0-alpha1 (pakiet przedpremierowy) środowisko korzysta z
VirtualPathProvider
dostępu do plików zamiast dotykać fizycznego systemu plików.Zaktualizowany transformator można zobaczyć poniżej:
źródło
Oto transformacja pakietu, która zastąpi adresy URL css adresami URL względem tego pliku css. Po prostu dodaj go do swojego pakietu i powinno to rozwiązać problem.
źródło
cannot convert type from BundleFile to FileInfo
Inną opcją byłoby użycie modułu IIS URL Rewrite do mapowania folderu obrazu pakietu wirtualnego na folder obrazu fizycznego. Poniżej znajduje się przykład reguły przepisywania, której można użyć dla pakietu o nazwie „~ / bundles / yourpage / styles” - zwróć uwagę na dopasowania wyrażenia regularnego znaków alfanumerycznych, a także łączników, podkreślników i kropek, które są powszechne w nazwach plików obrazów .
Takie podejście powoduje dodatkowe obciążenie, ale pozwala mieć większą kontrolę nad nazwami pakietów, a także zmniejsza liczbę pakietów, do których możesz odwoływać się na jednej stronie. Oczywiście, jeśli musisz odwoływać się do wielu plików css innych firm, które zawierają względne odwołania do ścieżki obrazu, nadal nie możesz obejść się przy tworzeniu wielu pakietów.
źródło
Rozwiązanie Grinn jest świetne.
Jednak nie działa dla mnie, gdy w adresie URL znajdują się odnośniki względne do folderu nadrzędnego. to znaczy
url('../../images/car.png')
Więc nieznacznie zmieniłem
Include
metodę, aby rozwiązać ścieżki dla każdego dopasowania wyrażenia regularnego, pozwalając na ścieżki względne, a także opcjonalnie osadzić obrazy w css.Zmieniłem również IF DEBUG, aby sprawdzić
BundleTable.EnableOptimizations
zamiastHttpContext.Current.IsDebuggingEnabled
.Mam nadzieję, że to pomaga, pozdrawiam.
źródło
Możesz po prostu dodać kolejny poziom głębi do ścieżki wirtualnego pakietu
Jest to bardzo mało zaawansowana technika i rodzaj hackowania, ale działa i nie wymaga wstępnego przetwarzania. Biorąc pod uwagę długość i złożoność niektórych z tych odpowiedzi, wolę robić to w ten sposób.
źródło
Miałem ten problem z pakietami mającymi niepoprawne ścieżki do obrazów i niepoprawne
CssRewriteUrlTransform
rozwiązywanie względnych ścieżek nadrzędnych..
(wystąpił również problem z zasobami zewnętrznymi, takimi jak strony internetowe). Właśnie dlatego napisałem tę niestandardową transformację (wydaje się, że wszystkie powyższe poprawnie wykonuję):Edycja: Nie zdawałem sobie z tego sprawy, ale użyłem niestandardowych metod rozszerzenia w kodzie. Ich kod źródłowy to:
Oczywiście powinno być możliwe do zastąpienia
String.StartsWith(char)
zString.StartsWith(string)
.źródło
m.Groups[2].Value.Count("..")
nie działa.) IValue.StartsWith('/')
nie działa, ponieważ StartsWith oczekuje ciągu zamiast znaku.Po krótkim dochodzeniu doszedłem do następujących wniosków: Masz 2 opcje:
iść z transformacjami. Bardzo przydatny pakiet do tego: https://bundletransformer.codeplex.com/ potrzebujesz każdej transformacji dla każdego problematycznego pakietu:
Zalety: w tym rozwiązaniu możesz nazwać swój pakiet, jak chcesz => możesz łączyć pliki css w jeden pakiet z różnych katalogów. Wady: Musisz przekształcić każdy problematyczny pakiet
źródło
CssRewriteUrlTransform
naprawiono mój problem.Jeśli po użyciu kod nadal nie ładuje obrazów
CssRewriteUrlTransform
, zmień nazwę pliku css z:Do:
W jakiś sposób. (Kropki) nie są rozpoznawane w adresie URL.
źródło
Pamiętaj tylko, aby naprawić wiele wtrąceń CSS w pakiecie, takich jak:
Nie można po prostu dodać
new CssRewriteUrlTransform()
do końca, tak jak można to zrobić za pomocą jednego pliku CSS, ponieważ metoda go nie obsługuje, dlatego należy użyćInclude
wiele razy :źródło