Is it possible to set breakpoints in razor views with servicestack? - razor

I am trying out the new razor view stuff in service stack, and I have this view:
#inherits ServiceStack.Razor.ViewPage<ServiceStackRazorCrud.Api.UserPageResourceResponse>
#{
var m = Model; // <-- I have a breakpoint in this line.
var req = Request;
var res = Response;
}
When I set a breakpoints and run the application (console application) I can see that the view is compiled but the debugger does not break when I request the view in the browser. I assume that this is because the views are compiled dynamically at application start or something like that. Is it possible somehow to get the breakpoints to work?

AFAIK it's not possible to debug views this way (currently using 3.9.43, later version I believe has better diagnostics for compilation errors).
Try and keep view code simple, restricted to simple loops/rendering and using extension methods on DTO's for any complex logic/processing, which do allow debugging. You might also consider utilizing logging, or a simple Debug extension method:
using ServiceStack.Html;
public static class HtmlHelperExtensions
{
public static bool IsDebug(this HtmlHelper htmlHelper)
{
#if DEBUG
return true;
#else
return false;
#endif
}
}
#using ServiceStack.Text
#inherits ServiceStack.Razor.ViewPage<ServiceStackRazorCrud.Api.UserPageResourceResponse>
#{
var m = Model;
}
#if (this.Html.IsDebug())
{
<div class="debug">#(this.Model == null ? "m == null" : Model.Dump())</div>
}

Related

Trying to get C++/WinRT non UWP program to recognize bluetooth LE devices: specific failure at get_weak() (error:not defined)

I'm taking a shot at using C++/WinRT to find and communicate with Bluetooth LE devices in a non-UWP app.
(I'm trying to avoid UWP, as there appear to be some constraints on what you can do with it, and it looks kind of bloated to me.)
My background is a lot of programming and releasing for small-group distribution old-fashioned C++ WinMain-based programming, as in Petzold's "Programming Windows 95". My experience has been using the Win32 API only.
Unfortunately for me, MS documentation indicates that Bluetooth LE is not supported in Win32, and only in WinRT. Thus, this forces me to use something like C++/WinRT to access the API.
So, I took a shot at it by downloading the only available example of bluetooth LE access in C++ which I know of at all, which is Microsoft's C++WinRT UWP example.
I got that running as one Visual Studio 2022 project, and, since I am looking for a non-UWP program, I tried putting the relevant stuff into another project, for which I used Microsoft VS2022's built-in template for a C++/WinRT Console. When I try to stick into that what appearVS says to be the key elements of the C++/WinRT UWP example, and make modifications to fix obvious problems, I have an error in the code which I have no idea how to fix: it is on the several get_weak() calls, which VS intellisense says are "undefined". (The compile also fails with unable to find main.g.h and main.g.cpp .
Here is the code:
File main.h:
#pragma once
#include "main.g.h"
class find_devs
{
find_devs() {};
private:
std::vector<Windows::Devices::Enumeration::DeviceInformation> UnknownDevices;
Windows::Devices::Enumeration::DeviceWatcher deviceWatcher{ nullptr };
event_token deviceWatcherAddedToken;
event_token deviceWatcherUpdatedToken;
event_token deviceWatcherRemovedToken;
event_token deviceWatcherEnumerationCompletedToken;
event_token deviceWatcherStoppedToken;
void StartBleDeviceWatcher();
void StopBleDeviceWatcher();
std::vector<Windows::Devices::Enumeration::DeviceInformation>::iterator FindUnknownDevices(hstring const& id);
fire_and_forget DeviceWatcher_Added(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Devices::Enumeration::DeviceInformation deviceInfo);
fire_and_forget DeviceWatcher_Updated(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Devices::Enumeration::DeviceInformationUpdate deviceInfoUpdate);
fire_and_forget DeviceWatcher_Removed(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Devices::Enumeration::DeviceInformationUpdate deviceInfoUpdate);
fire_and_forget DeviceWatcher_EnumerationCompleted(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Foundation::IInspectable const&);
fire_and_forget DeviceWatcher_Stopped(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Foundation::IInspectable const&);
};
and main.cpp:
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Devices::Enumeration;
#include "pch.h"
#include "main.h"
#include "main.g.cpp"
using namespace winrt;
using namespace Windows::Devices::Enumeration;
using namespace Windows::Foundation;
namespace winrt
{
hstring to_hstring(DevicePairingResultStatus status)
{
switch (status)
{
case DevicePairingResultStatus::Paired: return L"Paired";
case DevicePairingResultStatus::NotReadyToPair: return L"NotReadyToPair";
case DevicePairingResultStatus::NotPaired: return L"NotPaired";
case DevicePairingResultStatus::AlreadyPaired: return L"AlreadyPaired";
case DevicePairingResultStatus::ConnectionRejected: return L"ConnectionRejected";
case DevicePairingResultStatus::TooManyConnections: return L"TooManyConnections";
case DevicePairingResultStatus::HardwareFailure: return L"HardwareFailure";
case DevicePairingResultStatus::AuthenticationTimeout: return L"AuthenticationTimeout";
case DevicePairingResultStatus::AuthenticationNotAllowed: return L"AuthenticationNotAllowed";
case DevicePairingResultStatus::AuthenticationFailure: return L"AuthenticationFailure";
case DevicePairingResultStatus::NoSupportedProfiles: return L"NoSupportedProfiles";
case DevicePairingResultStatus::ProtectionLevelCouldNotBeMet: return L"ProtectionLevelCouldNotBeMet";
case DevicePairingResultStatus::AccessDenied: return L"AccessDenied";
case DevicePairingResultStatus::InvalidCeremonyData: return L"InvalidCeremonyData";
case DevicePairingResultStatus::PairingCanceled: return L"PairingCanceled";
case DevicePairingResultStatus::OperationAlreadyInProgress: return L"OperationAlreadyInProgress";
case DevicePairingResultStatus::RequiredHandlerNotRegistered: return L"RequiredHandlerNotRegistered";
case DevicePairingResultStatus::RejectedByHandler: return L"RejectedByHandler";
case DevicePairingResultStatus::RemoteDeviceHasAssociation: return L"RemoteDeviceHasAssociation";
case DevicePairingResultStatus::Failed: return L"Failed";
}
return L"Code " + to_hstring(static_cast<int>(status));
}
}
// This scenario uses a DeviceWatcher to enumerate nearby Bluetooth Low Energy devices,
// displays them in a ListView, and lets the user select a device and pair it.
// This device will be used by future scenarios.
// For more information about device discovery and pairing, including examples of
// customizing the pairing process, see the DeviceEnumerationAndPairing sample.
#pragma region UI Code
#pragma endregion
#pragma region Device discovery
/// <summary>
/// Starts a device watcher that looks for all nearby Bluetooth devices (paired or unpaired).
/// Attaches event handlers to populate the device collection.
/// </summary>
void find_devs::StartBleDeviceWatcher()
{
// Additional properties we would like about the device.
// Property strings are documented here https://msdn.microsoft.com/en-us/library/windows/desktop/ff521659(v=vs.85).aspx
auto requestedProperties = single_threaded_vector<hstring>({ L"System.Devices.Aep.DeviceAddress", L"System.Devices.Aep.IsConnected", L"System.Devices.Aep.Bluetooth.Le.IsConnectable" });
// BT_Code: Example showing paired and non-paired in a single query.
hstring aqsAllBluetoothLEDevices = L"(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")";
deviceWatcher =
Windows::Devices::Enumeration::DeviceInformation::CreateWatcher(
aqsAllBluetoothLEDevices,
requestedProperties,
DeviceInformationKind::AssociationEndpoint);
// Register event handlers before starting the watcher.
deviceWatcherAddedToken = deviceWatcher.Added({ get_weak(), &DeviceWatcher_Added });
deviceWatcherUpdatedToken = deviceWatcher.Updated({ get_weak(), &DeviceWatcher_Updated });
deviceWatcherRemovedToken = deviceWatcher.Removed({ get_weak(), &DeviceWatcher_Removed });
deviceWatcherEnumerationCompletedToken = deviceWatcher.EnumerationCompleted({ get_weak(), &DeviceWatcher_EnumerationCompleted });
deviceWatcherStoppedToken = deviceWatcher.Stopped({ get_weak(), &DeviceWatcher_Stopped });
// Start the watcher. Active enumeration is limited to approximately 30 seconds.
// This limits power usage and reduces interference with other Bluetooth activities.
// To monitor for the presence of Bluetooth LE devices for an extended period,
// use the BluetoothLEAdvertisementWatcher runtime class. See the BluetoothAdvertisement
// sample for an example.
deviceWatcher.Start();
}
/// <summary>
/// Stops watching for all nearby Bluetooth devices.
/// </summary>
void find_devs::StopBleDeviceWatcher()
{
if (deviceWatcher != nullptr)
{
// Unregister the event handlers.
deviceWatcher.Added(deviceWatcherAddedToken);
deviceWatcher.Updated(deviceWatcherUpdatedToken);
deviceWatcher.Removed(deviceWatcherRemovedToken);
deviceWatcher.EnumerationCompleted(deviceWatcherEnumerationCompletedToken);
deviceWatcher.Stopped(deviceWatcherStoppedToken);
// Stop the watcher.
deviceWatcher.Stop();
deviceWatcher = nullptr;
}
}
std::vector<Windows::Devices::Enumeration::DeviceInformation>::iterator FindUnknownDevices(hstring const& id)
{
}
fire_and_forget find_devs::DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation deviceInfo)
{
}
fire_and_forget find_devs::DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
{
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
auto deviceInfo = FindUnknownDevices(deviceInfoUpdate.Id());
if (deviceInfo != UnknownDevices.end())
{
deviceInfo->Update(deviceInfoUpdate);
// If device has been updated with a friendly name it's no longer unknown.
}
}
}
fire_and_forget find_devs::DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
{
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
auto deviceInfo = FindUnknownDevices(deviceInfoUpdate.Id());
if (deviceInfo != UnknownDevices.end())
{
UnknownDevices.erase(deviceInfo);
}
}
}
fire_and_forget find_devs::DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, IInspectable const&)
{
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
}
}
fire_and_forget DeviceWatcher_Stopped(DeviceWatcher sender, IInspectable const&)
{
// Access this->deviceWatcher on the UI thread to avoid race conditions.
auto lifetime = get_strong();
co_await resume_foreground(Dispatcher());
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
}
}
#pragma endregion
int main()
{
init_apartment();
Uri uri(L"http://aka.ms/cppwinrt");
printf("Hello, %ls!\n", uri.AbsoluteUri().c_str());
}
and, for completeness, this is pch.h
#pragma once
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Devices.Enumeration.h>
The code is, I know, not complete. I haven't created a DeviceWatcher, etc., but I am apparently blocked in that I can't get the get_weaks() to pass intellisense screening or to compile.
Any guidance from people who know about this stuff would be great.
Bear in mind: I, myself, pretty much don't know what's going on. Due to the complexity, from my Win32 Petzold-style background, of the example MS C++/WinRT UWP example. It has all kinds of stuff in the Solution Explorer. There are .idl files, a packages.config, a bunch of different Xaml files, some generated c++ files. All this stuff is beyond my understanding, and I have not been able to pick it up with any speed from the MS documentation I can find.
(All I have figured out is that C++/WinRT is some sort of a thing where there are generated header and perhaps other files that are supposed to make your C++ code look like it's directly accessing WinRT classes. And, I have seen MS write that you can use winRT in non-UWP applications. Otherwise, I am lost.)

Razor engine cant find view

I'm trying to render a HTML from a view without using a web request. I need the HTML as a string, internally, I do not wish to serve it.
The viewEngine.FindView() returns a viewEnineResult that shows no view was found. It shows to search locations where it looked they look like this:
/Views//PDFOperationsReportView.cshtml
/Views/Shared/PDFOperationsReportView.cshtml
(Observe the double forward slash in the first line)
File structure (I placed it into a HTML snippet cause I couldn't manage to format the text properly in this editor)
Project
Folder
Subfolder
CodeFile.cs
Views
PDFOperationsReportView.cshtml
The code:
var viewName = "PDFOperationsReportView";
var actionContext = GetActionContext();
var viewEngineResult = _viewEngine.FindView(actionContext, viewName, false);
if (!viewEngineResult.Success)
{
throw new InvalidOperationException(string.Format("Couldn't find view '{0}'", viewName));
}
var view = viewEngineResult.View;
I had the same issue. I found the answer here: GitHub aspnet/Mvc Issue #4936
Basically, use GetView instead of FindView, like this:
var viewResult = razorViewEngine.GetView(viewName, viewName, false);
Your viewName needs to be a full path for this to work. For example:
/Views/Shared/PDFOperationsReportView.cshtml
~/Pages/Shared/_Article.cshtml
~/Areas/CM/Pages/_Article.cshtml
We have a helper method defined to render optional views which may or may not exist:
public static Task RenderPartialAsyncIfExists(this IHtmlHelper htmlHelper, ICompositeViewEngine engine, string partialViewName, object model)
{
if (engine.GetView(partialViewName, partialViewName, false).Success)
{
return htmlHelper.RenderPartialAsync(partialViewName, model);
}
return Task.CompletedTask;
}
It's used on view pages like:
#inject ICompositeViewEngine Engine
...
#{ await Html.RenderPartialAsyncIfExists(Engine, $"~/Views/Shared/_navigationAdmin.cshtml"); }
This works find locally (IIS Express) but for some reason was failing when deployed to IIS.
In my case, there was something wrong with the .csproj file, where the view in question was removed but then re-added as an embedded resource:
<ItemGroup>
<Content Remove="Views\Shared\_navigationAdmin.cshtml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Views\Shared\_navigationAdmin.cshtml" />
</ItemGroup>
Removing those two sections from the .csproj fixed the problem in IIS.
This is using (EOL) AspNet Core 2.2

How do I allow an MIME extension map in ASP.NET vNext?

Background
I have a piece of LESS code that needs to be compiled at runtime with Less.js -- it calculates some things via JavaScript -- so I can't use the task runner, etc.
In my index.html, I have:
<head>
...
<link rel="stylesheet/less" href="assets/less/DynamicHeight.less" />
...
<script type="text/javascript" src="lib/less/less.js"></script>
...
</head>
Problem
Less.js appears unable to find the file:
And when I try to access the file directly, I see:
Question
How can I add the configuration that will allow this less file to be downloaded? Am I still able to use web.config files with vNext, or do I need to do something with config.json instead?
Lead 1: Should I use Owin?
Thinking this might be the right path but I'm pretty unfamiliar.
I see a number of tutorials out there, such as K. Scott Allen's, which reference code such as:
public void Configuration(IAppBuilder app)
{
var options = new StaticFileOptions
{
ContentTypeProvider = new FileExtensionContentTypeProvider()
};
((FileExtensionContentTypeProvider)options.ContentTypeProvider).Mappings.Add(
new KeyValuePair<string, string>(".less", "text/css"));
app.UseStaticFiles(options);
}
However, it appears that in its current version, asp.net is looking for a signature of Configure(IApplicationBuilder app) instead.
The IApplicationBuilder class doesn't have a method along the lines of UseStaticFiles -- it only has a signature of IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware).
I have a feeling that this is likely the right path to solve the issue -- I just can't find out how to propertly configure the IAppliationBuilder to map the MIME extension.
Okay, I believe I figured it out.
Step 1: Add the appropriate library for static files
In ASP.NET vNext, this is Microsoft.Aspnet.StaticFiles.
In your project.json file, add the following under "dependencies":
"Microsoft.AspNet.StaticFiles": "1.0.0-beta2"
This adds the static middleware method that you can use later.
Step 2: Configure the app to use Static Files
Add the using statement at the top:
using Microsoft.AspNet.StaticFiles;
At this point, the app.UseStaticFiles method will be available, so your Configure method can look as follows:
public void Configure(IApplicationBuilder app)
{
var options = new StaticFileOptions
{
ContentTypeProvider = new FileExtensionContentTypeProvider()
};
((FileExtensionContentTypeProvider)options.ContentTypeProvider).Mappings.Add(
new KeyValuePair<string, string>(".less", "text/css"));
app.UseStaticFiles(options);
}
And voila! I get text when browsing to .less files, and no more error is appearing from LessJS.
In .NET Core 1.0.1, SeanKileen answer is still good. The following is a simple code rewrite:
public void Configure(IApplicationBuilder app, ...)
var contentTypeProvider = new FileExtensionContentTypeProvider();
contentTypeProvider.Mappings[".map"] = "application/javascript";
contentTypeProvider.Mappings[".less"] = "text/css";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = contentTypeProvider
});
The above code EXTENDS the default mapping list (see the source), which already has ~370 mappings.
Avoid using the FileExtensionContentTypeProvider constructor overload that takes a dictionary (as suggested by JHo) if you want those 370 default mappings.
SeanKilleen's answer is right on, and still works ASP.NET Core RC1. My only improvement is to write the exact same code using collection initializers to make it cleaner.
app.UseStaticFiles(new StaticFileOptions
{
ContentTypeProvider = new FileExtensionContentTypeProvider(new Dictionary<string, string>
{
{ ".less", "text/css" },
{ ".babylon", "text/json" },
// ....
})
});

Rendering an email throws a TemplateCompilationException using RazorEngine 3 in a non-MVC project

I am trying to render emails in a windows service host.
I use RazorEngine 3 forked by coxp which has support for Razor 2.
https://github.com/coxp/RazorEngine/tree/release-3.0/src
This works fine for a couple of emailtemplates but there is one causing me problems.
#model string
Click here to enter a new password for your account.
This throws a CompilationException: The name 'WriteAttribute' does not exist in the current context. So passing in a string as model and putting it in the href-attribute causes problems.
I can make it work by changing this line by:
#Raw(string.Format("Klik hier.", #Model))
but this makes the template very unreadable and harder to pass along to a marketing department for further styling.
I like to add that referencing the RazorEngine by using a Nuget package is not a solution since it is based on Razor 1 and somewhere along the process the DLL for system.web.razor gets replaced by version 2 which breaks any code using RazorEngine. It seems more interesting to use Razor 2 to benefit from the new features and to be up to date.
Any suggestions on how to fix this would be great. Sharing your experiences is also very welcome.
UPDATE 1
It seems like calling SetTemplateBaseType might help, but this method does not exist anymore, so I wonder how to be able to bind the templatebasetype?
//Missing method in the new RazorEngine build from coxp.
Razor.SetTemplateBaseType(typeof(HtmlTemplateBase<>));
I use Windsor to inject the template service rather than using the Razor object. Here is a simplified part of the code that shows how to set the base template type.
private static ITemplateService CreateTemplateService()
{
var config = new TemplateServiceConfiguration
{
BaseTemplateType = typeof (HtmlTemplateBase<>),
};
return new TemplateService(config);
}
RazorEngine 3.1.0
Little bit modified example based on coxp answer without the injection:
private static bool _razorInitialized;
private static void InitializeRazor()
{
if (_razorInitialized) return;
_razorInitialized = true;
Razor.SetTemplateService(CreateTemplateService());
}
private static ITemplateService CreateTemplateService()
{
var config = new TemplateServiceConfiguration
{
BaseTemplateType = typeof (HtmlTemplateBase<>),
};
return new TemplateService(config);
}
public static string ParseTemplate(string name, object model)
{
InitializeRazor();
var appFileName = "~/EmailTemplates/" + name + ".cshtml";
var template = File.ReadAllText(HttpContext.Current.Server.MapPath(appFileName));
return RazorEngine.Razor.Parse(template, model);
}

How does one cshtml call a function in another cshtml?

In webmatrix I have created a DAL.cshtml in App_Data with lots of public static functions.
I want to call them from a different .cshtml page in a different folder.
Presently I get
Compiler Error Message: CS0103: The name DAL does not exist in the current context
(note I'm a beginner following a blog about moving the data access to a single location)
In my DAL.cshtml an example is:
public static void AddProfile (dynamic Profile)
{
var sql = "INSERT INTO profile (ProfileDescription, ProfileType) " +
"VALUES (#0, #1)";
PinwheelDB.Execute(sql, Profile.ProfileDescription, Profile.ProfileType);
var Profile.ProfileID = PinwheelDB.GetLastInsertId();
}
In my 'calling' .cshtml I have:
dynamic Profile = new ExpandoObject();
Profile.ProfileDescription = Request.Form["txtChildFirstName"];
Profile.ProfileType = 1;
functions.DAL.AddProfile(Profile);
var vProfileID = Profile.ProfileID;
Once I moved the DAL.cshtml into a folder called App_Code instead of App_Data (Thank-you Darin) it just worked.
Please note that the code I have ended up with is as follows (in case it helps another beginner)........
DAL.cshtml now in a folder called App_Code I have:
#functions
{
public static void AddProfile (dynamic Profile)
{
var sql = "......"
PinwheelDB.Execute(sql, .......);
}
The calling .cshtml
remains as I first quoted
If anyone knows why this is I'd like to understand.
You could put commonly used methods in classes in the App_Code folder. For example you could have a ~/App_Code/DAL.cs:
public class DAL
{
public static void AddProfile(dynamic profile)
{
...
}
}
and in your calling Razor page:
#{
var profile = ...
DAL.AddProfile(profile);
}