I have implemented applinks to handle all the url's from my domain as follows
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.example.com"
android:scheme="http" />
</intent-filter>
but i would like to open some links from the same domain in customtabs.I am implementing this logic to invoke those links in customtabs
CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
#Override
public void onCustomTabsServiceConnected(ComponentName componentName, CustomTabsClient client) {
client.warmup(0L);
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
builder.setInstantAppsEnabled(false);
builder.setToolbarColor(context.getResources().getColor(R.color.pure_white));
builder.setSecondaryToolbarColor(context.getResources().getColor(R.color.pure_white));
builder.setShowTitle(true);
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(context,Uri.parse("http://www.example.com/unhandled"));
}
#Override
public void onServiceDisconnected(ComponentName name) {}
};
CustomTabsClient.bindCustomTabsService(context, "com.android.chrome", connection);
but those links were captured by my applink intent and it goes on in a loop.What am i missing? Any ideas or suggestions would be useful.
Setting the package on the Intent that launches the CustomTabs should force it to open Chrome.
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.intent.setPackage("com.android.chrome");
customTabsIntent.launchUrl(
context,Uri.parse("http://www.example.com/unhandled"));
Also, since Chrome is not the only browser that supports Custom Tabs, I'd recommend following the best practices, and supporting other browsers as well.
Related
while trying to Add bearer token using Swashbuckle swagger-document
i got this error in SwaggerConfig.cs
swaggeruiconfig does not contain definition for 'EnableApiKeySupport'
do any body know what may be the reason
Update
this is the entire swagger.config
using System.Web.Http;
using WebActivatorEx;
using Swashbuckle.Application;
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
namespace AppNameSpace
{
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.ApiKey("Token")
.Description("Filling bearer token here")
.Name("Authorization")
.In("header");
c.SingleApiVersion("v2", "AppNameSpace");
c.IncludeXmlComments(GetXmlCommentsPath());
})
.EnableSwaggerUi(c =>
{
c.EnableApiKeySupport("Authorization", "header");
});
}
protected static string GetXmlCommentsPath()
{
return System.String.Format(#"{0}\bin\AppNameSpace.XML", System.AppDomain.CurrentDomain.BaseDirectory);
}
}
}
This I believe is something on your project outside Swashbuckle, I created a test project with your GlobalConfiguration and it compiles without any error:
https://github.com/heldersepu/csharp-proj/tree/master/WebApi560
On that test project I'm using the following packages:
<package id="Swashbuckle" version="5.6.0" targetFramework="net452" />
<package id="Swashbuckle.Core" version="5.6.0" targetFramework="net452" />
<package id="WebActivatorEx" version="2.0" targetFramework="net452" />
You can try seeing what options are available for the SwaggerUiConfig...
in your VisualStudio project remove the EnableApiKeySupport and let the IntelliSense show you what's available, you should see something like:
If yours does not look like the one on my picture. You might be overwriting the class SwaggerUiConfig.
I followed the example - https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/custom-renderer/hybridwebview/ to create a hybrid web view. It works fine in Andriod project but I have issues with the iOS project. In the OnElementChanged override, the Element property is always Xamarin.Forms.Element type which is the base type and not my generic view type (TElement). I have rechecked my code multiple times but cannot find any fixes. If I download the original code and run it, it works fine. The issue is only in my project.
Can anybody give me pointers as to why I might not be getting the generic TElement type. In the original project , the TElement type is HybridWebView. In mine I have a different name but with almost all the same properties and methods.
Below are some of my code. It is really easy to replicate the issue. Just create a new Xamarin.Forms solution and add my code. You will see the issue on this lie - var ele = Element; //ELEMENT HERE IS NOt SBMHybridWebView
The custom control in PCL
public class SBMHybridWebView : Xamarin.Forms.View
{
}
The iOS Renderer (off-course I have added the ExportRenderer)
public class SBMHybridWebViewRenderer : ViewRenderer<SBMHybridWebView, WKWebView>, IWKScriptMessageHandler
{
const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
WKUserContentController userController;
protected override void OnElementChanged(ElementChangedEventArgs<SBMHybridWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
userController = new WKUserContentController();
var script = new WKUserScript(new NSString(JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
userController.AddUserScript(script);
userController.AddScriptMessageHandler(this, "invokeAction");
var config = new WKWebViewConfiguration { UserContentController = userController };
var webView = new WKWebView(Frame, config);
SetNativeControl(webView);
}
if (e.OldElement != null)
{
//Clean up code
}
if (e.NewElement != null)
{
var ele = Element; //ELEMENT HERE IS NOt SBMHybridWebView
}
}
public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
{
//Element.InvokeAction(message.Body.ToString());
}
}
The XAML
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:localcontrol="clr-namespace:App2.Control;assembly=App2"
x:Class="App2.View.Page1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="60" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<localcontrol:SBMHybridWebView Grid.Row="0" />
</Grid>
</ContentPage>
I found the cause which I cannot explain. In my iOS project, I had my SBMHybridWebViewRenderer in Renderer folder. Somehowm iOS does not like the renderer to be in a folder. Moving it to the root of the project (but keeping the same namespace) solved the issue. WHY? I dont know. I would have expected it to work regardless of where I place the file.
I thought I will post this just incase someone else has the same issue.
I would like to configure HTML minification to my ASP>NET MVC5 web application.
I installed Nuget
Install-Package WebMarkupMin.Mvc
Then I add Filter Attributte:
[MinifyHtmlAttribute]
public ActionResult Index()
{
return View();
}
But the HTML minification does not work.
Nuget Installation add few lines to the web.config:
<sectionGroup name="webMarkupMin">
<section name="core" type="WebMarkupMin.Core.Configuration.CoreConfiguration, WebMarkupMin.Core" />
<section name="webExtensions" type="WebMarkupMin.Web.Configuration.WebExtensionsConfiguration, WebMarkupMin.Web" />
</sectionGroup>
<webMarkupMin xmlns="http://tempuri.org/WebMarkupMin.Configuration.xsd">
<core>
<css>
<minifiers>
<add name="NullCssMinifier" displayName="Null CSS Minifier" type="WebMarkupMin.Core.Minifiers.NullCssMinifier, WebMarkupMin.Core" />
<add name="KristensenCssMinifier" displayName="Mads Kristensen's CSS minifier" type="WebMarkupMin.Core.Minifiers.KristensenCssMinifier, WebMarkupMin.Core" />
</minifiers>
</css>
<js>
<minifiers>
<add name="NullJsMinifier" displayName="Null JS Minifier" type="WebMarkupMin.Core.Minifiers.NullJsMinifier, WebMarkupMin.Core" />
<add name="CrockfordJsMinifier" displayName="Douglas Crockford's JS Minifier" type="WebMarkupMin.Core.Minifiers.CrockfordJsMinifier, WebMarkupMin.Core" />
</minifiers>
</js>
<html whitespaceMinificationMode="Medium" removeHtmlComments="true"
removeHtmlCommentsFromScriptsAndStyles="true"
removeCdataSectionsFromScriptsAndStyles="true"
useShortDoctype="true" useMetaCharsetTag="true"
emptyTagRenderMode="NoSlash" removeOptionalEndTags="true"
removeTagsWithoutContent="false" collapseBooleanAttributes="true"
removeEmptyAttributes="true" attributeQuotesRemovalMode="Html5"
removeRedundantAttributes="true"
removeJsTypeAttributes="true" removeCssTypeAttributes="true"
removeHttpProtocolFromAttributes="false"
removeHttpsProtocolFromAttributes="false"
removeJsProtocolFromAttributes="true"
minifyEmbeddedCssCode="true" minifyInlineCssCode="true"
minifyEmbeddedJsCode="true" minifyInlineJsCode="true"
processableScriptTypeList="" minifyKnockoutBindingExpressions="false"
minifyAngularBindingExpressions="false" customAngularDirectiveList="" />
<logging>
<loggers>
<add name="NullLogger" displayName="Null Logger" type="WebMarkupMin.Core.Loggers.NullLogger, WebMarkupMin.Core" />
<add name="ThrowExceptionLogger" displayName="Throw exception logger" type="WebMarkupMin.Core.Loggers.ThrowExceptionLogger, WebMarkupMin.Core" />
</loggers>
</logging>
</core>
</webMarkupMin>
The html element was added by me manually according to documentation.
Am I missing something?
Web application may be in debug mode. In order to switch it to release mode you need to edit the Web.config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
<system.web>
<compilation debug="false" ... />
...
</system.web>
...
</configuration>
In addition, you can disable dependence on web application mode. Using the following settings:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
<webMarkupMin xmlns="http://tempuri.org/WebMarkupMin.Configuration.xsd">
<webExtensions disableMinificationInDebugMode="false"
disableCompressionInDebugMode="false" />
...
</webMarkupMin>
...
</configuration>
So large library with so difficult usage and configuration... Are you sure need all this for just the HTML minification?
Create a new filter under the Filters subfolder of your project and call it CompactHtmlFilterAttribute Use the following code:
public class CompactHtmlFilterAttribute : ActionFilterAttribute
{
public class WhitespaceFilter : MemoryStream
{
private string Source = string.Empty;
private Stream Filter = null;
public WhitespaceFilter(HttpResponseBase HttpResponseBase)
{
Filter = HttpResponseBase.Filter;
}
public override void Write(byte[] buffer, int offset, int count)
{
Source = UTF8Encoding.UTF8.GetString(buffer).Replace("\r", "").Replace("\n", "").Replace("\t", "");
Filter.Write(UTF8Encoding.UTF8.GetBytes(Source), offset, UTF8Encoding.UTF8.GetByteCount(Source));
}
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
#if DEBUG
base.OnActionExecuting(filterContext);
#else
try
{
filterContext.HttpContext.Response.Filter = new WhitespaceFilter(filterContext.HttpContext.Response);
}
catch (Exception) { }
#endif
}
}
Pay atention on the #if DEBUG dirrective. HTML will be minified only in release configuration, while on debug the original code will be kept for the better readability.
Add this attribute to the controller methods
[CompactHtmlFilter]
public ActionResult Index()
{
return View();
}
and we're done.
You need to add the following to enable the webextensions (from the doc):
<webMarkupMin xmlns="http://tempuri.org/WebMarkupMin.Configuration.xsd">
…
<webExtensions enableMinification="true" disableMinificationInDebugMode="true"
enableCompression="true" disableCompressionInDebugMode="true"
maxResponseSize="100000" disableCopyrightHttpHeaders="false" />
…
</webMarkupMin>
Note that it's outside the <core> element.
also in your view markup you should have the attribute as:
[MinifyHtml]
Itshouldn't have the ..Attribute at the end of it.
I have an issue with understanding how flash works in the jsf lifecycle.
I am trying to redirect to a different page from a phase listener through a normal get request and at the same time adding a flash message(of course i have set the flah.keepmessage) to be displayed on the new page. But the message fails to show up. I know that something is wrong and will be grateful if anyone can kindly assist in implementing a better way (without filters please).
phaseredirect1.html
<h:body>
<f:view>
<f:phaseListener binding="#{testphase.testPL}"/>
<div>Testing Phases Redirect 1</div>
</f:view>
</h:body>
TestPhaseRedirect.java
#SessionScoped
#ManagedBean(name="testphase")
public class TestPhaseRedirect {
private PhaseListener testPL;
#PostConstruct
private void initializeVar(){
testPL = new PhaseListener() {
#Override
public void afterPhase(PhaseEvent event) {
}
#Override
public void beforePhase(PhaseEvent event) {
getFacesContext().addMessage(null, new FacesMessage("Faces Message: redirecting to page 2..."));
getExternalContext().getFlash().setKeepMessages(true);
ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler)getFacesContext().getApplication().getNavigationHandler();
nav.performNavigation("redirect-to-page2");
getFacesContext().responseComplete();
return;
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RENDER_RESPONSE;
}
};
}
public PhaseListener getTestPL() {
return testPL;
}
}
phaseredirect2.html
<h:body>
<f:view>
<div style="width:400px;">
<p:messages autoUpdate="true" closable="true"/>
<p>Testing Phases Redirect 2</p>
<p> Did it display the message? </p>
</div>
</f:view>
</h:body>
faces config
<navigation-case>
<from-outcome>redirect-to-page2</from-outcome>
<to-view-id>/phaseredirect2.html</to-view-id>
<redirect />
</navigation-case>
Kindly correct me.
Thank you so much.
During the render response phase, it's too late to create the flash scope. You need to do it at latest during invoke application phase. Basically, this problem has the same grounds as when doing so in a <f:event type="preRenderView"> as already answered in the following related questions:
Adding faces message to redirected page using ExternalContext.redirect()
Mojarra 2.1.14 flash scope messages and redirect to different path
In your particular case, you need a dummy view parameter so that the invoke action phase is triggered and then use the <f:event type="postInvokeAction"> (after having created the custom event yourself or having installed OmniFaces as per the answers on the abovelinked questions):
<f:metadata>
<f:viewParam name="dummy" />
<f:event type="postInvokeAction" listener="#{bean.init}" />
</f:metadata>
with
public void init() {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Faces Message: redirecting to page 2..."));
context.getExternalContext().getFlash().setKeepMessages(true);
ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler) context.getApplication().getNavigationHandler();
nav.performNavigation("redirect-to-page2");
}
or if you've chosen for OmniFaces
public void init() {
Messages.addFlashGlobalInfo("Faces Message: redirecting to page 2...");
Faces.navigate("redirect-to-page2");
}
I have a simple Facelet tag:
<ui:composition>
<ui:insert />
</ui:composition>
which is used in order to avoid declaring multiple c:set tags.
Let's say I registered it in the facelets taglib library with the name view, and use it like this:
<my:view bean="#{myController}">
<p:inputText value="#{bean.value}>
<p:ajax event="blur" process="#this" listener="#{bean.handleValueChanged}" />
</p:inputText>
</my:view>
The attribute value is perfectly resolved by p:inputText, but p:ajax throws this:
Target Unreachable, identifier 'bean' resolved to null
javax.el.PropertyNotFoundException: Target Unreachable, identifier 'bean' resolved to null
at com.sun.el.parser.AstValue.getTarget(AstValue.java:153)
at com.sun.el.parser.AstValue.invoke(AstValue.java:237)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:302)
at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:39)
at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
at org.primefaces.component.behavior.ajax.AjaxBehaviorListenerImpl.processAjaxBehavior(AjaxBehaviorListenerImpl.java:47)
Is it a bug or expected behavior?
Update:
I just tried the same with f:ajax and it worked!
Btw, the environment is as follows:
Glassfish 3.1.2
PF 3.0, 3.2, 3.3
Update2:
This issue with RichFaces is absolutely identical. Seems to be like a PrimeFaces bug (I'll post an issue on PF bug tracker today).
My colleague has just provided a patch to resolve this issue.
The current implementation of AjaxBehaviorListenerImpl#processAjaxBehaviour is as follows:
public void processAjaxBehavior(AjaxBehaviorEvent event) throws AbortProcessingException {
FacesContext context = FacesContext.getCurrentInstance();
final ELContext elContext = context.getELContext();
try{
listener.invoke(elContext, new Object[]{});
} catch (MethodNotFoundException mnfe) {
MethodExpression argListener = context.getApplication().getExpressionFactory().
createMethodExpression(elContext, listener.getExpressionString(), null, new Class[]{event.getClass()});
argListener.invoke(elContext, new Object[]{event});
}
}
He proposes to tweak it like this:
import javax.faces.view.facelets.FaceletContext;
public void processAjaxBehavior(AjaxBehaviorEvent event) throws AbortProcessingException {
FacesContext context = FacesContext.getCurrentInstance();
final ELContext elContext = context.getELContext();
try{
listener.invoke(elContext, new Object[]{});
} catch (MethodNotFoundException mnfe) {
FaceletContext fc = (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
MethodExpression argListener = context.getApplication().getExpressionFactory().
createMethodExpression(fc, listener.getExpressionString(), null, new Class[]{ event.getClass() });
argListener.invoke(elContext, new Object[]{ event });
}
}
Hopefully this will be approved by PF team.
The tweak does not work with my use case which is more complex than a single ui:include.
<c:forEach items="#{items}" var="item">
<ui:include src="#{item.uri}">
<ui:param name="itemBean" value="#{item.bean}"/>
</ui:include>
</c:forEach>
I think the listener's variable mapper must be reused inside the new MethodExpression