Minha pergunta é semelhante a esta:
Só que eu quero ficar com o próprio pacote do MVC, se puder. Estou tendo um acidente cerebral tentando descobrir qual é o padrão correto para especificar pacotes de estilos, de modo que CSS e conjuntos de imagens independentes, como o jQuery UI, funcionem.
Eu tenho uma estrutura de site MVC típica com a /Content/css/
qual contém meu CSS base, como styles.css
. Dentro dessa pasta css, também tenho subpastas como a /jquery-ui
que contém seu arquivo CSS mais uma /images
pasta. Os caminhos de imagem no CSS da UI do jQuery são relativos a essa pasta e não quero mexer com eles.
Pelo que entendi, ao especificar um StyleBundle
, preciso especificar um caminho virtual que também não corresponda a um caminho de conteúdo real, porque (assumindo que estou ignorando rotas para o Conteúdo), o IIS tentaria resolver esse caminho como um arquivo físico. Então, eu estou especificando:
bundles.Add(new StyleBundle("~/Content/styles/jquery-ui")
.Include("~/Content/css/jquery-ui/*.css"));
processado usando:
@Styles.Render("~/Content/styles/jquery-ui")
Eu posso ver a solicitação saindo para:
http://localhost/MySite/Content/styles/jquery-ui?v=nL_6HPFtzoqrts9nwrtjq0VQFYnhMjY5EopXsK8cxmg1
Isso está retornando a resposta CSS correta e minificada. Mas o navegador envia uma solicitação para uma imagem relativamente vinculada como:
http://localhost/MySite/Content/styles/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
Qual é um 404
.
Entendo que a última parte do meu URL jquery-ui
é um URL sem extensão, um manipulador para o meu pacote, para que eu possa entender por que a solicitação relativa da imagem é simples /styles/images/
.
Então, minha pergunta é qual é a maneira correta de lidar com essa situação?
fonte
Respostas:
De acordo com este encadeamento no MVC4, empacotamento de css e referências de imagem , se você definir seu pacote como:
Onde você define o pacote configurável no mesmo caminho que os arquivos de origem que compunham o pacote configurável, os caminhos de imagem relativos ainda funcionarão. A última parte do caminho do pacote configurável é realmente a do
file name
pacote configurável específico (ou seja,/bundle
pode ser o nome que você quiser).Isso só funcionará se você estiver agrupando CSS da mesma pasta (o que eu acho que faz sentido da perspectiva de agrupar).
Atualizar
De acordo com o comentário abaixo de @Hao Kung, agora isso pode ser conseguido aplicando um
CssRewriteUrlTransformation
( Altere as referências de URL relativas aos arquivos CSS quando agrupadas ).NOTA: Não confirmei comentários sobre problemas com a reescrita para caminhos absolutos em um diretório virtual; portanto, isso pode não funcionar para todos (?).
fonte
A solução Grinn / ThePirat funciona bem.
Eu não gostei do fato de ele ter iniciado o método Include no pacote e de ter criado arquivos temporários no diretório de conteúdo. (eles acabaram sendo registrados, implantados e o serviço não iniciava!)
Então, para seguir o design do Bundling, optei por executar essencialmente o mesmo código, mas em uma implementação IBundleTransform:
Em seguida, envolva isso em uma Implementação de pacote configurável:
Uso da amostra:
Aqui está o meu método de extensão para RelativeFromAbsolutePath:
fonte
relativeToCSS
antes de ligarPath.GetFullPath()
.Melhor ainda (IMHO) implementar um pacote personalizado que corrige os caminhos da imagem. Eu escrevi um para o meu aplicativo.
...
Para usá-lo, faça:
...ao invés de...
O que ele faz é (quando não está no modo de depuração) procura
url(<something>)
e o substitui porurl(<absolute\path\to\something>)
. Eu escrevi a coisa cerca de 10 segundos atrás, para que possa precisar de alguns ajustes. Levei em consideração URLs totalmente qualificadas e DataURIs base64, certificando-me de que não haja dois pontos (:) no caminho da URL. Em nosso ambiente, as imagens normalmente residem na mesma pasta que os arquivos css, mas eu testei com as pastas pai (url(../someFile.png)
) e filho (url(someFolder/someFile.png
).fonte
Não é necessário especificar uma transformação ou ter caminhos de subdiretório louco. Depois de muita solução de problemas, eu o isolei dessa regra "simples" (é um bug?) ...
Se o caminho do pacote configurável não iniciar com a raiz relativa dos itens incluídos, a raiz do aplicativo da web não será levada em consideração.
Parece mais um bug para mim, mas de qualquer maneira é assim que você o corrige com a versão atual do .NET 4.51. Talvez as outras respostas fossem necessárias em versões mais antigas do ASP.NET, não posso dizer que não tenho tempo para testar retrospectivamente tudo isso.
Para esclarecer, aqui está um exemplo:
Eu tenho esses arquivos ...
Em seguida, configure o pacote como ...
E torná-lo como ...
E obtenha o "comportamento" (bug), os arquivos CSS possuem a raiz do aplicativo (por exemplo, "http: // localhost: 1234 / MySite / Content / Site.css"), mas a imagem CSS em todo o início "/ Content / Images / ... "ou" / Images / ... "dependendo se eu adiciono a transformação ou não.
Até tentei criar a pasta "Bundles" para ver se tinha a ver com o caminho existente ou não, mas isso não mudou nada. A solução para o problema é realmente o requisito de que o nome do pacote configurável comece com a raiz do caminho.
O que significa que este exemplo é corrigido registrando e renderizando o caminho do pacote configurável como ..
Portanto, é claro que você poderia dizer que é RTFM, mas tenho certeza de que eu e outros buscamos esse caminho "~ / Bundles / ..." no modelo padrão ou em algum lugar da documentação no site MSDN ou ASP.NET, ou simplesmente tropeçou nele, porque na verdade é um nome bastante lógico para um caminho virtual e faz sentido escolher caminhos virtuais que não entrem em conflito com diretórios reais.
Enfim, é assim que é. A Microsoft não vê nenhum bug. Não concordo com isso: ele deve funcionar conforme o esperado ou alguma exceção deve ser lançada ou uma substituição adicional para adicionar o caminho do pacote que opta por incluir a raiz do aplicativo ou não. Não consigo imaginar por que alguém não gostaria que a raiz do aplicativo fosse incluída quando houvesse uma (normalmente, a menos que você tenha instalado seu site com um alias de DNS / raiz padrão do site). Então, na verdade, esse deve ser o padrão de qualquer maneira.
fonte
Descobri que CssRewriteUrlTransform falha ao executar se você estiver referenciando um
*.css
arquivo e tiver o*.min.css
arquivo associado na mesma pasta.Para corrigir isso, exclua o
*.min.css
arquivo ou faça referência a ele diretamente em seu pacote configurável :Depois disso, seus URLs serão transformados corretamente e suas imagens deverão ser resolvidas corretamente.
fonte
Talvez eu seja tendencioso, mas eu gosto bastante da minha solução, pois ela não faz nenhuma transformação, etc de regex e tem a menor quantidade de código :)
Isso funciona para um site hospedado como um diretório virtual em um site do IIS e como um site raiz no IIS
Então, eu criei uma implementação de
IItemTransform
encapsuladoCssRewriteUrlTransform
e usadoVirtualPathUtility
para corrigir o caminho e chamar o código existente:Parece funcionar bem para mim?
fonte
Embora a resposta de Chris Baxter ajude com o problema original, ela não funciona no meu caso quando o aplicativo está hospedado no diretório virtual . Depois de investigar as opções, terminei com a solução DIY.
ProperStyleBundle
A classe inclui código emprestado do originalCssRewriteUrlTransform
para transformar adequadamente os caminhos relativos no diretório virtual. Também lança se o arquivo não existir e impede a reordenação de arquivos no pacote (código retiradoBetterStyleBundle
).Use-o como
StyleBundle
:fonte
A partir da v1.1.0-alpha1 (pacote de pré-lançamento), a estrutura usa o
VirtualPathProvider
para acessar arquivos em vez de tocar no sistema de arquivos físico.O transformador atualizado pode ser visto abaixo:
fonte
Aqui está uma transformação de pacote configurável que substituirá os URLs CSS por URLs relativos a esse arquivo CSS. Basta adicioná-lo ao seu pacote e ele deve corrigir o problema.
fonte
cannot convert type from BundleFile to FileInfo
Outra opção seria usar o módulo Regravação de URL do IIS para mapear a pasta da imagem do pacote virtual para a pasta da imagem física. Abaixo está um exemplo de uma regra de reescrita que você pode usar para um pacote chamado "~ / bundles / yourpage / styles" - observe que a regex corresponde a caracteres alfanuméricos, bem como hífens, sublinhados e pontos, comuns em nomes de arquivos de imagem .
Essa abordagem cria um pouco de sobrecarga extra, mas permite que você tenha mais controle sobre os nomes dos pacotes configuráveis e também reduz o número de pacotes configuráveis que você pode ter que fazer referência em uma página. Obviamente, se você precisar fazer referência a vários arquivos css de terceiros que contenham referências relativas ao caminho da imagem, ainda não conseguirá criar vários pacotes configuráveis.
fonte
A solução Grinn é ótima.
No entanto, isso não funciona para mim quando há referências relativas à pasta pai no URL. ie
url('../../images/car.png')
Então, mudei um pouco o
Include
método para resolver os caminhos para cada correspondência de regex, permitindo caminhos relativos e, opcionalmente, incorporar as imagens no css.Também alterei o IF DEBUG para verificar em
BundleTable.EnableOptimizations
vez deHttpContext.Current.IsDebuggingEnabled
.Espero que ajude, cumprimentos.
fonte
Você pode simplesmente adicionar outro nível de profundidade ao caminho do seu pacote virtual
Essa é uma resposta super baixa tecnologia e meio que um hack, mas funciona e não requer pré-processamento. Dada a extensão e complexidade de algumas dessas respostas, prefiro fazê-lo dessa maneira.
fonte
Eu tive esse problema com pacotes configuráveis com caminhos incorretos para imagens e
CssRewriteUrlTransform
não resolvendo..
corretamente os caminhos pai relativos (também houve problemas com recursos externos, como webfonts). Foi por isso que escrevi essa transformação personalizada (parece fazer tudo isso acima corretamente):Editar: não percebi, mas usei alguns métodos de extensão personalizados no código. O código fonte desses é:
Obviamente, deve ser possível substituir
String.StartsWith(char)
porString.StartsWith(string)
.fonte
m.Groups[2].Value.Count("..")
não funciona.) EValue.StartsWith('/')
também não funciona porque StartsWith espera uma string em vez de um caractere.Após pouca investigação, concluí o seguinte: Você tem 2 opções:
vá com transformações. Pacote muito útil para isso: https://bundletransformer.codeplex.com/, você precisa da seguinte transformação para cada pacote problemático:
Vantagens: desta solução, você pode nomear seu pacote configurável como desejar => você pode combinar arquivos css em um pacote configurável de diretórios diferentes. Desvantagens: Você precisa transformar todos os pacotes problemáticos
fonte
CssRewriteUrlTransform
corrigiu meu problema.Se o seu código ainda não carrega imagens após o uso
CssRewriteUrlTransform
, altere o nome do arquivo css de:Para:
De alguma forma. (Pontos) não estão reconhecendo no URL.
fonte
Lembre-se de corrigir várias inclusões CSS em um pacote, como:
Você não pode simplesmente adicionar
new CssRewriteUrlTransform()
até o final, como pode com um arquivo CSS, pois o método não o suporta; portanto, você deve usarInclude
várias vezes :fonte