RIA Service Error in a Silverlight Application - silverlight

In a very simple Silverlight Application I have a DomainService Class which has a single method that returns a list of Letter Objects.
The application works fine when I run it in VisualStudio. However, when I publish it to a folder on my Windows 10 local machine and run it using IIS (version 10.0.166299.5) I get the following error:
The remote server returned an error: NotFound.
at System.ServiceModel.DomainServices.Client.OperationBase.Complete(Exception error) at System.ServiceModel.DomainServices.Client.LoadOperation.Complete(Exception error) at System.ServiceModel.DomainServices.Client.DomainContext.CompleteLoad(IAsyncResult asyncResult) at System.ServiceModel.DomainServices.Client.DomainContext.<>c__DisplayClass1b.b__17(Object )
I supect this is due to something being wrong in missing in my WebConfig file. My WebConfig Currently looks like this:
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.6" />
<httpRuntime targetFramework="4.6" />
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<add name="DomainServiceModule" preCondition="managedHandler" type="System.ServiceModel.DomainServices.Hosting.DomainServiceHttpModule, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</modules>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
The code for my Domain Service Class is like this:
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using SilverData.Web.Models;
namespace SilverData.Web.Services
{
[EnableClientAccess]
public class DrugsRiaService : DomainService
{
public IQueryable<Letter> GetAllLetters()
{
List<Letter> letters = new List<Letter>();
Letter letterA = new Letter { ID = 1, Statement = "Mike" };
Letter LetterB = new Letter { ID = 2, Statement = "Emma" };
Letter LetterC = new Letter { ID = 3, Statement = "Peter" };
letters.Add(letterA);
letters.Add(LetterB);
letters.Add(LetterC);
return letters.AsQueryable();
}
}
}

The error was due to the problem that .svc file wasn't being served.. The problem got solved with the kind help from the Kyle Abraham on Experts Exchange.
https://www.experts-exchange.com/questions/29084691/RIA-Service-Error-in-a-Silverlight-Application.html
The solution was to add the following line to the webserver section of the Webconfig
<handlers>
<add name=".svc" verb="*" path="*.svc" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</handlers>

I'm not sure, its a guess as I have not used RIA for awhile, but I think letters needs to returned as something other than queryable... try ToList() which causes the query to execute, and the payload is complete with the complete enumeration that was retrieved from the database. Remember, this is a remote call from a client, not a local one that can extend the queryable.

Related

How to resolve key/value pair with external .config file

I am specifying <appSettings> in my app.config file, I am adding
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings configSource="ShareAppSettings.debug.config"/>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
</startup>
</configuration>
ShareAppSettigns.debug.config is my external config file, which I am using on my local machine and I do not want to share it with the rest of my team.
ShareAppSettings.debug.config looks like:
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<add key="clientID" value="11" />
<add key="clientSecret" value="11" />
<add key="tenantID" value="11" />
</appSettings>
Whenever I am trying to debug the main code:
private static List<string> AppCredentials()
{
string clientID = ConfigurationManager.AppSettings["clientID"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
string tenantID = ConfigurationManager.AppSettings["tenantID"];
List<string> appCred = new List<string> { clientID, clientSecret, tenantID };
if (clientID == null)
throw new Exception("ShareAppSettings.Debug.Config file was not provided in this repo.");
return (appCred);
}
For some reason I am not getting values for clientId, slientSecret nor tenantId. This code is a part of grasshopper Add-on for v6 template, and its running on .NET Framework 4.7.1. Whenever I copy the same code into a new C# console of a same framework, the code is built. I would truly appreciate if you could give me suggestions on how to solve this.
What "EnableWindowsFormsHighDpiAutoResizing" means and how can make this work?
Many Thanks
enter image description here
I suggest to use the file attribute (corresponding to the AppSettingsSection.File property) instead of the configSource attribute (corresponding to the SectionInformation.ConfigSource property) in the appSettings section.
configSource doesn't support other keys in the section, while appSettings may contain other keys, needed by the Application and possibly somewhere else (someone else may add/remove them - for testing purposes or any other reason).
The file attribute allows instead the presence of other key in the appSettings section.
Your app.config file can be:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings file="ShareAppSettings.debug.config">
<add key="DpiAwareness" value="PerMonitorV2"/>
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
</startup>
</configuration>
Now the values are accessible by both opening a named configuration section:
appSettings.Settings[] returns a KeyValueConfigurationElement
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
AppSettingsSection appSettings = (AppSettingsSection)config.GetSection("appSettings");
var kvpClientID = appSettings.Settings["clientID"];
var kvpClientSecret = appSettings.Settings["clientSecret"];
var kvpCenantID = appSettings.Settings["tenantID"];
string clientID = kvpClientID.Value;
and directly, using ConfigurationManager.AppSettings - a NameValueCollection - which returns the value of the specified key:
string clientID = ConfigurationManager.AppSettings["clientID"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
string tenantID = ConfigurationManager.AppSettings["tenantID"];
As a note, using the file attribute, your ShareAppSettings.debug.config doesn't need (but it's not forbidden) the XML header, it can be just:
<appSettings>
<add key="clientID" value="11" />
<add key="clientSecret" value="11" />
<add key="tenantID" value="11" />
</appSettings>
Secondary note:
you can set the file attribute to point to another file at run-time and refresh the appSettings values to updated the configuration.
Note that, if a file attribute was already set, all values contained in that .config file are not dismissed, but instead moved to the [Application].exe.config file, to become part of the <appSettings> section (thus, they are preserved).
Another reason why using the file attribute may be preferable.
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var appSettings = config.AppSettings;
appSettings.File = "SomeOtherFile.config";
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");

Can't insert into SQL Server table with log4net AdoNetAppender

I am trying to understand how log4net works so I've added this to my app.config (I should add that Console Appender and FileAppender work perfectly, I only have trouble with the AdoNetAppender).
How can I debug this, to see if at least the connection to db succeeds?
The problem is the INSERT statement isn't executed.
I should add the
Data Source=MyWorkgroup\SQLEXPRESS;Initial Catalog=MyNewDatabase;User ID=juan;password=juan,
works perfectly when I try to connect to SQL Server manually, so not sure if that's the problem.
Also, the ConnectionType was taken from the official site:
https://logging.apache.org/log4net/log4net-1.2.11/release/sdk/log4net.Appender.AdoNetAppender.ConnectionType.html
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net"
type="log4net.Config.log4netConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="AdoNetAppender"
type="log4net.Appender.AdoNetAppender">
<bufferSize value="10" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="Data Source=MyWorkgroup\SQLEXPRESS;Initial Catalog=MyNewDatabase;User ID=juan;Password=juan;Pooling=False" />
<commandText value="INSERT INTO Logs([logDate],[logThread],[logMessage]) VALUES(getdate(),'1','1')" />
<commandType value="Text" />
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="AdoNetAppender"/>
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
Later edit (after using the debug method recommended by David):
haacked.com is indeed extremely interesting, great tip! However, it seems that it's describing what I'm instructing log4net to log, but not the result of those actions(?), if I'm reading this well (no failed/or succeeded?)
e.g.
log4net: Setting Property [ConnectionType] to String value
[System.Data.SqlClien t.SqlConnection, System.Data,
Version=1.0.3300.0, Culture=neutral, PublicKeyToke n=b77a5c561934e089]
log4net: Setting Property [ConnectionString] to String value [Data
Source=MyWorkgroup\SQLEXPRESS; Initial
Catalog=MyNewDatabase;
User ID=juan; Password=juan;
Pooling=False] log4net: Setting Property [CommandText] to String value [INSERT INTO Logs([logDate],[logThread],[logMessage]) VALUES(getdate(),'1','1')] log4net:
Setting Property [CommandType] to CommandType value [Text] log4net:
Created Appender [AdoNetAppender] log4net: Adding appender named
[AdoNetAppender] to logger [root]. log4net: Hierarchy Threshold []
Piece of code that helped me obtain this info (in case the site should become unavailable) is:
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add
name="textWriterTraceListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="C:\temp\log4netdiagn.txt" />
</listeners>
</trace>
</system.diagnostics>

Unable to cast object of type 'System.Web.Security.SqlRoleProvider' to type 'WebMatrix.WebData.SimpleRoleProvider'

I developing an mvc web app with Entity Frame]work. I've enabled database migration so that i can add some seed data on each update.
More specifically, i want to add two users and two roles; so the configuration file looks like this:
var roles = (SimpleRoleProvider)Roles.Provider;
var membership = (SimpleMembershipProvider)Membership.Provider;
//// create two roles
if (!roles.RoleExists("Admin"))
{
roles.CreateRole("Admin");
}
if (!roles.RoleExists("User"))
{
roles.CreateRole("User");
}
However there seems to be a problem during the casting; it throws an exception
Unable to cast object of type 'System.Web.Security.SqlRoleProvider' to type 'WebMatrix.WebData.SimpleRoleProvider'.
I suspect that this might be a configuration issue, but i'm not really sure. Does anyone stumbled across the same problem?
That's because SqlRoleProvider does not inherit SimpleRoleProvider. However, you can try using SimpleRoleProvider Constructor (RoleProvider):
var roles = new SimpleRoleProvider(Roles.Provider);
I sorted this out. The problem apparently was related to web configuration. I added the following lines to the web.config file:
<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
to explicitly set the role provider. So now the Roles.Provider returns an instance of WebMatrix.WebData.SimpleRoleProvider; thus i don't need to cast any more
I solved this by placing below code in web.config between
<roleManager enabled="true" defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
<membership defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>

MVC 4 - after seeding database webpages_Roles is still empty

So I have basic MVC 4 Internet application project with Entity Framework 5.
I have configured WebSecurity that uses my table for users.
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "Email", autoCreateTables: true);
Then in my migration configuration class I seed DB with new roles and add users to them.
internal sealed class Configuration : DbMigrationsConfiguration<Infrastructure.KlepecV2Db>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(Infrastructure.KlepecV2Db context)
{
if(!Roles.RoleExists("Admin"))
{
Roles.CreateRole("Admin");
}
if (!Roles.RoleExists("Test1"))
{
Roles.CreateRole("Test1");
}
if(Membership.GetUser("user1") != null)
{
if(!Roles.IsUserInRole("user1","Admin"))
{
Roles.AddUserToRole("user1", "Admin");
}
}
if (Membership.GetUser("user2") != null)
{
if (!Roles.IsUserInRole("user2", "Admin"))
{
Roles.AddUserToRole("user2", "Admin");
}
}
}
}
So when I type "update-database" in NuGet console everything gets executed without errors. But if I look into webpages_Roles table its empty. Also webpages_UsersInRoles is empty.
For testing I have removed Role.RoleExists() calls and updating database fails, becouse roles already exists.
What am I missing here? Where are this roles stored?
I came across into an error The Role Manager feature has not been enabled mentioned by #Magnus. Hope this probably related to your roles issue in which the default role provider is unknown.
The error The Role Manager feature has not been enabled happened when I move the WebSecurity.InitializeDatabaseConnection method from MVC project into a class library (data access) for code first migration seed.
The point is App.config need to be configured for Package Manager Update-Database command to be run just like when Web.config exist.
Below is my App.config and Seed. Note that
I add "DefaultConnection" connection string *
Add system.web->roleManager to set the enable="true"
Add runtime->assemblyBinding->qualifyAssembly to give hint to compiler where is WebMatrix.WebData by giving the full assembly name.
App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<!--<add name="DefaultConnection" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=Db;Persist Security Info=True;User=user;Password=pass" providerName="System.Data.SqlClient" />-->
</connectionStrings>
<system.web>
<roleManager enabled="true" defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
<membership defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
</system.web>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<qualifyAssembly partialName="WebMatrix.WebData" fullName="WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
</entityFramework>
</configuration>
Seed Method:
protected override void Seed(DatabaseContext context)
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "Email", autoCreateTables: true);
if(!Roles.RoleExists("Admin"))
{
Roles.CreateRole("Admin");
}
if (!Roles.RoleExists("Test1"))
{
Roles.CreateRole("Test1");
}
if(Membership.GetUser("user1") != null)
{
if(!Roles.IsUserInRole("user1","Admin"))
{
Roles.AddUserToRole("user1", "Admin");
}
}
if (Membership.GetUser("user2") != null)
{
if (!Roles.IsUserInRole("user2", "Admin"))
{
Roles.AddUserToRole("user2", "Admin");
}
}
}
Hope this will help anyone with The Role Manager feature has not been enabled issue when using code first migration seed in a class library.
Update
* EF5 will read the connection string in Web.config of Mvc project but not in the App.config of the project with EF Migrations. However the membership and roleManager settings is still required in the EF Migration project.
Wanted to add my $0.02 to the conversation. I have a similar setup to CallMeLaNN, but was still getting the error. My solution was to set my "Data" project to a StartUp project. After that, my app.config file started getting picked up, and I can now seed my users from the Update-Database command.

silverlightFaultBehavior for WCF - but still getting code 500

I want to get a meaningful error message from my WCF service for my Silverlight 4 application. After some investigation, I found that I need to change the reply code from 500 to 200 if I want silverlight enable to read the meaningful error message. Here is the article: http://msdn.microsoft.com/de-de/library/ee844556(VS.95).aspx
I have implemented it as it is written there, the application compiles and I can use the service - but I still get the 500 return code. The main difference I see is that I call the service via HTTPS not HTTP. Maybe this is the reason, why it doesn't work? Any idea, how to get the return code 200?
Here is my Web.Config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="ServiceConfiguratorDataSource.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="silverlightFaults" type="ServiceConfiguratorDataSource.SilverlightFaultBehavior, ServiceConfiguratorDataSource, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<services>
<service name="ServiceConfiguratorDataSource.Service" behaviorConfiguration="ServiceConfiguratorDataSourceBehaviour">
<endpoint address="" binding="customBinding" behaviorConfiguration="SLFaultBehavior" bindingConfiguration="ServiceConfiguratorCustomBinding" contract="ServiceConfiguratorDataSource.IService" />
</service>
</services>
<bindings>
<customBinding>
<binding name="ServiceConfiguratorCustomBinding">
<security authenticationMode="UserNameOverTransport"></security>
<binaryMessageEncoding></binaryMessageEncoding>
<httpsTransport/>
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceConfiguratorDataSourceBehaviour">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="True"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ServiceConfiguratorDataSource.UserCredentialsValidator,ServiceConfiguratorDataSource" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="SLFaultBehavior">
<silverlightFaults/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
... and here the silverlightFaultBehavior.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel;
namespace ServiceConfiguratorDataSource
{
public class SilverlightFaultBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
SilverlightFaultMessageInspector inspector = new SilverlightFaultMessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
public class SilverlightFaultMessageInspector : IDispatchMessageInspector
{
public void BeforeSendReply(ref Message reply, object correlationState)
{
if (reply.IsFault)
{
HttpResponseMessageProperty property = new HttpResponseMessageProperty();
// Here the response code is changed to 200.
property.StatusCode = System.Net.HttpStatusCode.OK;
reply.Properties[HttpResponseMessageProperty.Name] = property;
}
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Do nothing to the incoming message.
return null;
}
}
// The following methods are stubs and not relevant.
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
public override System.Type BehaviorType
{
get { return typeof(SilverlightFaultBehavior); }
}
protected override object CreateBehavior()
{
return new SilverlightFaultBehavior();
}
}
}
Someone knows if this is because of https ... and if so, how to get it to work?
Thanks in advance,
Frank
EDITH says: I just have added some logging: the ApplyDispatchBehavior - method is called, but the BeforeSendReply - method not ... any ideas why?
If I remember correctly, the UserNamePasswordValidator gets called very early in the pipeline, before the dispatcher ever gets called, which is why your custom dispatch behavior isn't affecting anything. (The reason is security: WCF wants to "throw out" unauthorized requests as early as possible, while running as little code as possible for them).
As you yourself suggested in the comments, one solution would be to just validate the credentials later in the pipeline - e.g. in every operation (or maybe even in a message inspector's AfterReceiveRequest?)

Resources