Universal Windows Platform app with Visual Studio 2015 (RTM)
I have a DataTemplate that is used in multiple pages of my app, so I'd prefer to write it once and access it from anywhere I need to. In order to make it accessible by any page, I write it in my App.xaml's <Application.Resources>:
<Application
x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp"
xmlns:viewmodels="using:MyApp.ViewModels"
RequestedTheme="Light">
<Application.Resources>
<DataTemplate x:Key="DetailContentTemplate" x:DataType="viewmodels:DataViewModel">
...
</DataTemplate>
</Application.Resources>
The DataTemplate portion of the code above works just fine in an individual page, but of course that means I'd have to copy and paste it multiple times to other pages, which just isn't efficient. However, I get this error when I use the DataTemplate in App.xaml:
XBF generation error code 0x09c4
I've determined that it stems from the x:DataType="viewmodels:DataViewModel" (without this, and hence, without any bindings the code works just fine). Looking up the error results in next to nothing. Is there a convenient workaround/solution to being able to reuse a DataTemplate with bindings in a Universal Windows Platform/WinRT app, preferably in XAML?
EDIT: As requested, the code in full for App.xaml.cs:
namespace MyApp
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Allows tracking page views, exceptions and other telemetry through the Microsoft Application Insights service.
/// </summary>
public static Microsoft.ApplicationInsights.TelemetryClient TelemetryClient;
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
TelemetryClient = new Microsoft.ApplicationInsights.TelemetryClient();
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
// Set the default language
rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
rootFrame.NavigationFailed += OnNavigationFailed;
if (rootFrame.Content == null)
{
rootFrame.Navigate(typeof(MasterDetailPage));
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
// Ensure the current window is active
Window.Current.Activate();
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}
You can find some explanation here from the latest build session at 20:10
You basically need to create a resource dictionary in XAML and attach a class to it. This class file is needed to allow the compiler to generate its code.
Depending on what you have to do and how you can change your code, you can still use the "old" {Binding} markup which will work as before.
<Application.Resources>
<DataTemplate x:Key="DetailContentTemplate">
<TextBlock Text={Binding myValue} />
</DataTemplate>
</Application.Resources>
Related
Is it possible to create our own HTTP method by just overriding the HttpMethodAttribute class and specify our own supportedMethods ?
In fact, depending on the case, we need to return the View as complete view with the _Layout, and sometimes we just need to return the PartialView of this view. So my idea is to put an custom attribute, like [HttpPartial] and so the client will tell, depending on the methods used in the request, if it wants the complete view (GET method) or the partial view (PARTIAL method).
Yes, that's possible for APIs. You can look at how the HttpGetAttribute is implemented, and roll your own for a custom method, replacing "get" with "foo":
/// <summary>
/// Identifies an action that supports the HTTP FOO method.
/// </summary>
public class HttpFooAttribute : HttpMethodAttribute
{
private static readonly IEnumerable<string> _supportedMethods = new[] { "FOO" };
/// <summary>
/// Creates a new <see cref="HttpFooAttribute"/>.
/// </summary>
public HttpFooAttribute()
: base(_supportedMethods)
{
}
/// <summary>
/// Creates a new <see cref="HttpFooAttribute"/> with the given route template.
/// </summary>
/// <param name="template">The route template. May not be null.</param>
public HttpFooAttribute(string template)
: base(_supportedMethods, template)
{
if (template == null)
{
throw new ArgumentNullException(nameof(template));
}
}
}
Then apply it to your API action methods:
[Route("Bar")]
public class BarApiController : Controller
{
[HttpFoo("/"]
public IActionResult Foo()
{
return Ok("Foo");
}
}
Now you can request FOO https://your-api:44312/bar/.
This is less useful for actions returning views, as any HTML-rendering user agent only lets the user initiate GET or POST requests through hyperlinks and forms.
You could send more methods through an XMLHttpRequest or fetch(), but it'll require more documentation and client customization.
Don't break or hamper the web, don't invent new HTTP methods for your application logic. Simply use a query string parameter or send it in your body: &renderAsPartial=true, { "renderAsPartial": true }.
See the IANA's Hypertext Transfer Protocol (HTTP) Method Registry for existing methods and see RCF 7231 section 8.1 for how to register new HTTP methods.
Is it not possible to target different logging providers based on which logger is used?
For example, refer to the below code:
// Establish loggers
var someLogger = loggerFactory.CreateLogger("SomeLogger");
var anotherLogger = loggerFactory.CreateLogger("AnotherLogger");
// Hook up providers (but not at the individual logger's level??)
loggerFactory.AddDebug(minimumLevel: LogLevel.Debug);
loggerFactory.AddConsole(minimumLevel: LogLevel.Debug);
loggerFactory.AddBlob(connectionString, minimumLevel: LogLevel.Information);
// Log stuff
someLogger.LogError("Logging with someLogger");
anotherLogger.LogError("Logging with anotherLogger");
All providers will be logged too here, regardless of which logger is used.
Is this really not possible? What is the point of defining separate loggers if they all log to every provider regardless?
I'm not sure if that's possible but what you can do is log messages of different log levels to different providers. The example below logs all warning level messages and above to the event log using the SourceSwitch API. The use case here which may satisfy your needs is that you may not want information or debug messages filling up your event log.
private static void ConfigureLogging(ILoggerFactory loggerFactory)
{
var sourceSwitch = new SourceSwitch("EventLog");
sourceSwitch.Level = SourceLevels.Warning;
loggerFactory.AddTraceSource(sourceSwitch, new EventLogTraceListener("Application"));
}
UPDATE
ASP.NET 5 is very light on examples at the moment but the AddProvider method on ILoggerFactory is used to add it's own custom providers specific to it:
/// <summary>
/// Used to create logger instances of the given name.
/// </summary>
public interface ILoggerFactory : IDisposable
{
/// <summary>
/// The minimum level of log messages sent to registered loggers.
/// </summary>
LogLevel MinimumLevel { get; set; }
/// <summary>
/// Creates a new ILogger instance of the given name.
/// </summary>
/// <param name="categoryName"></param>
/// <returns></returns>
ILogger CreateLogger(string categoryName);
void AddProvider(ILoggerProvider provider);
}
So you could create another ILoggerFactory but register different providers to it. Then inject the right ILoggerFactory into your classes depending on where you want to log to.
I am handing exception in Controller, and other layers that I have manually added like DataAccess.
I have also placed exception handling in Views.
Is it necessary to do so, or can I remove the exception handling code from view?
This is not necessary, ASP.NET haves exception handling by itself. You only have to throw a exception. The view will catch it automatically when running on 'release' mode
Just add the 'FilterConfig' in your App_start
public class FilterConfig
{
/// <summary>
/// The register global filters.
/// </summary>
/// <param name="filters">
/// The filters.
/// </param>
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
I have two questions related to WCF Data Service:
is there a way to restrict the entities visible to a user according to her privileges ? For instance user in role super-user should be able to query the full 'Contact' entity but user with less privileges would only be able to see specific properties of the 'Contact' entity.
whenever a user runs a query on the service, I would like this to be logged in a database for audit purpose. Is this possible ?
1) There is the concept of interceptors: http://msdn.microsoft.com/en-us/library/dd744842.aspx
But I think they won't satisfy you in your case:
With change interceptors you can handle requests which try to change a specific entity. This could help you to avoid users without certain privileges to add/change/delete contact entities. With QueryInterceptors you can handle GET-Requests. But they don't allow you to restrict certain properties of your contact entity.
You are not the first with such requirements -> WCF Dataservice - modify object before returning results?
Maybe you could use a combination of a (custom) ServiceOperation and a View to handle this.
2) Yes, you can do this for instance by handling the ProcessingRequest-Event:
public class YourService : DataService<Entities>
{
/// <summary>
/// The logger.
/// </summary>
private readonly LogWriter logger;
/// <summary>
/// Initializes a new instance of the <see cref="YourService"/> class.
/// </summary>
public YourService()
{
this.logger = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
this.ProcessingPipeline.ProcessingRequest += this.ProcessingPipelineProcessingRequest;
}
/// <summary>
/// OnProcessingRequest
/// </summary>
/// <param name="sender">source</param>
/// <param name="e">event args</param>
public void ProcessingPipelineProcessingRequest(object sender, DataServiceProcessingPipelineEventArgs e)
{
this.logger.Write(new LogEntry { Message = "SOP ProcessingPipelineProcessingRequest: Unauthorized Access", Severity = TraceEventType.Warning })
}
}
You can find all those ProcessingPipeline-Events here: http://msdn.microsoft.com/en-us/library/system.data.services.dataserviceprocessingpipeline(v=vs.103).aspx
Usually when the Page_Load event handler is added to a codebehind file by Visual Studio (e.g. double clicking the page in designer mode), it ends up looking like this:
/// <summary>
/// Handles the Load event of the Page control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void Page_Load(object sender, EventArgs e)
{
// ...
}
But Resharper suggests Name 'Page_Load' does not match rule 'Methods, properties and events'. Suggested name is 'PageLoad'. I'm guessing there's a better way to define the handler for page load, but I can't remember what the syntax is, but I imagine it would resolve this Resharper warning?
Perhaps something like:
/// <summary>
/// Raises the <see cref="E:System.Web.UI.Control.Load"/> event.
/// </summary>
/// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// ...
}
but I seem to recall that OnLoad and PageLoad aren't exactly the same?
Just for completeness I thought I would add here the answer you got from one "David Benson" when you asked on jetbrains.net:
If you go to ReSharper Options, under Languages select C# Naming Style. Select the Advanced settings... button and in the Event subscriptions on fields:, remove the On in front of $event$ so it is $object$_$event$. That should remove the warning.
For me this is the easiest way of placating ReSharper in the face of a large existing web application codebase.
OnLoad and Page_Load are essentially the same. Page_Load is invoked via reflection if AutoEventWireup is enabled on the Page. OnLoad is a protected virtual method of the Control class (which the Page class inherits).
See Inside AutoEventWireup for an in-depth analysis of how AutoEventWireup works and why it exists.
The StackOverflow community also has some input on whether it is better to handle the Load event or override the OnLoad method.
It's a bug in ReSharper 6.0 and lower. In 6.1 it's fixed.
For AutoEventWireup handlers it will not suggest any changes doesn't matter which naming settings you have.