Store initialisation:
private static IDocumentStore CreateDocumentStore()
{
var store = (DocumentStore) new EmbeddableDocumentStore
{
ConnectionStringName = "RavenDb",
};
NonAdminHttp.EnsureCanListenToWhenInNonAdminContext(8080);
store.Initialize();
store.Conventions.MaxNumberOfRequestsPerSession = 500;
return store;
}
Config:
</configSections>
<appSettings>
<add key="Raven/Port" value="8080"/>
<add key="Raven/DataDir" value="~\#App_Data"/>
<add key="Raven/AnonymousAccess" value="Get" />
</appSettings>
<connectionStrings>
<clear/>
<add name="RavenDb" connectionString="DataDir=~\#App_Data\Raven" />
</connectionStrings>
The application works and raven persists some of the data, I just can't get to the management studio
By default the studio isn't served. You have to enable RavenDB's embedded web server when constructing the store instance:
var store = (DocumentStore) new EmbeddableDocumentStore
{
ConnectionStringName = "RavenDb",
UseEmbeddedHttpServer = true
};
Related
When I start my application, I get this error:
The ConnectionString property has not been initialized.
I am getting this exception while trying to connect to my SQL Server database.
Register.aspx.cs
protected void btnRegister_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = string.Format("insert into member
values('{0}','{1}','{2}','{3}','{4}','{5}','{6}')",
txtFullName.Text, rblGender.SelectedValue, ddlCountry.SelectedValue,
txtPhone.Text, txtEmail.Text, txtUsername.Text, txtPassword.Text);
try
{
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
tblRegister.Visible = false;
Response.Write("Your account is created.");
}
catch(SqlException ex)
{
if (ex.Number == 2627)
lblMsg.Text = "Please Change The Username.";
else
lblMsg.Text = "An Error : " + ex.Message;
}
}
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.6.1"/>
<httpRuntime targetFramework="4.6.1"/>
</system.web>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs"
type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider,
Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701"/>
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider,
Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+"/>
</compilers>
</system.codedom>
<appSettings>
<add key="ValidationSettings:UnobtrusiveValidationMode" value="None" />
</appSettings>
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=.\sqlexpress;Initial Catalog=Company;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
You need to do it like this:
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Data Source=MSSQL1;Initial Catalog=AdventureWorks;Integrated Security=true;"";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
With ConnectionString you specify which server to connect to and with what credentials, if not it won't know where you want to connect to and with what.
The example I gave is for SQL server and integrated security, depending on you database, server and your credentials you need to find the connection string you need
I'm using OWIN authentication and testing my Web APIs locally and I got some errors about CORS. I solved the problem just by adding customeHeaders tag in web.config. Now I'm able to login and and also get data. But when I try to PUT or DELETE requests, I get 404 (Not Found) error.
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Remove(config.Formatters.XmlFormatter);
var jsonFormatter = new JsonMediaTypeFormatter();
config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));
}
}
and in web.config
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="*" />
<add name="Access-Control-Allow-Headers" value="*" />
</customHeaders>
</httpProtocol>
I'm going to implement basic authentication in WCF. I'm very new in all this stuff and my program is based on this series of articles http://leastprivilege.com/2008/01/11/http-basic-authentication-against-non-windows-accounts-in-iisasp-net-part-0-intro/ I do use webHttpBinding and HTTPS is on.
So the main idea is implementation of IHttpModule in this way:
When user requests some resource a module checks if Authorization header is present.
In case of Authorization is present, the module extracts the header's value, decodes and checks login and pass
In the other case the module sends a response with 401 code and a header "WWW-Authenticate".
Here is my implementation of the module:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Management;
using System.Text;
namespace MyProj_A
{
public class MyHTTPModule : IHttpModule
{
void IHttpModule.Dispose()
{
}
void IHttpModule.Init(HttpApplication context)
{
context.BeginRequest += Context_BeginRequest;
context.AuthenticateRequest += OnEnter;
context.EndRequest += OnLeave;
}
private void Context_BeginRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
context.Response.Write("BeginRequest");
}
void OnEnter(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (IsHeaderPresent())
{
if (!AuthenticateUser())
{
DenyAccess();
}
}
else
{
// if anonymous requests are not allowed - end the request
DenyAccess();
}
}
bool IsHeaderPresent()
{
return HttpContext.Current.Request.Headers["Authorization"] != null;
}
bool AuthenticateUser()
{
string username = "", password = "";
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic"))
{
// extract credentials from header
string[] credentials = ExtractCredentials(authHeader);
username = credentials[0];
password = credentials[1];
if (username.CompareTo("tikskit") == 0 && password.CompareTo("") == 0)
{
return true;
} else
{
return false;
}
}
else
{
return false;
}
}
private static void DenyAccess()
{
HttpContext context = HttpContext.Current;
context.Response.StatusCode = 401;
context.Response.End();
}
void OnLeave(object sender, EventArgs e)
{
// check if module is enabled
if (HttpContext.Current.Response.StatusCode == 401)
{
SendAuthenticationHeader();
}
}
private void SendAuthenticationHeader()
{
HttpContext context = HttpContext.Current;
context.Response.StatusCode = 401;
context.Response.AddHeader(
"WWW-Authenticate",
"Basic realm=\"yo-ho-ho\""
);
}
}
}
I publish it under IIS 7.5 on remote computer and connect to it with remote debugger from my Visual Studio. I set breakpoints at Context_BeginRequest, OnEnter and OnLeave.
Then I access to my WCF from a browser using URL and here is what happens:
After I inputted an URL and pressed the Enter Context_BeginRequest is fired
In VS I can see that the Authorization header isn't present
OnEnter is fired and eventually it assigns 401 code to the response
OnLeave is executed as well and it sets WWW-Authenticate to the response header
In the browser the standart login dialog is shown
I input the user name and password and press OK
Now Context_BeginRequest is fired again and I can see that Authorization header is present and consists a value like "Basic ", which is right
OnEnter isn't executed at all this time
OnLeave is fired but a value of HttpContext.Current.Response.StatusCode is 401 by some reason
Here is my Web.config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2"/>
<customErrors mode="Off" />
</system.web>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp automaticFormatSelectionEnabled="false"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Default" >
<serviceMetadata httpGetEnabled="false" />
<serviceMetadata httpsGetEnabled="false"/>
<serviceAuthenticationManager authenticationSchemes="Basic"/>
<serviceCredentials>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="MyBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</webHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="MyProj_A.Service1">
<endpoint address="" binding="webHttpBinding" contract="MyProj_A.IService1"
behaviorConfiguration="webBehavior"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost/" />
</baseAddresses>
</host>
</service>
</services>
<diagnostics>
<endToEndTracing activityTracing="false" messageFlowTracing="true" propagateActivity="true"></endToEndTracing>
</diagnostics>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="MyHTTPModule"
type="MyProj_A.MyHTTPModule,MyProj-A"/>
</modules>
<directoryBrowse enabled="false"/>
</system.webServer>
</configuration>
So my questions are
1. Why OnEnter isn't fired second time, in 8, and how is 401 assigned in an item 9?
2. How to work around this behaviour, I mean do I need to move all the authentication processing from AuthenticateRequest (OnLeave) to BeginRequest (Context_BeginRequest) for example? Or maybe there is a better place for such processing?
Thanks!
Case is closed
I've forgotten to refer to binding configuration in endpoint configuration:
<endpoint address="" binding="webHttpBinding"
contract="MyProj_A.IService1"
behaviorConfiguration="webBehavior"
**bindingConfiguration="MyBinding"**/>
I'm new to WebApi and the tutorial was going well. I got Get, Get with variables, Post, and Delete to work, but I can't seem to get Put to work. Well, if I remove all the variables from the method the in the controller, it actually goes into the method, but that's pretty useless. Has anyone come across this before that knows how to fix it?
PUT Url sent to Postman:
http://localhost:60679/api/incident/1234
Preview:
PUT /api/incident/1234 HTTP/1.1
Host: localhost:60679
Cache-Control: no-cache
Error Message:
{"Message":"No HTTP resource was found that matches the request URI
'http://localhost:60679/api/incident/1234'.","MessageDetail":"No action was found on the
controller 'Incident' that matches the request."}
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebApiTest.AppLogic;
using WebApiTest.Data.Core;
namespace WebApiTest.WebApi.Controllers
{
public class IncidentController : ApiController
{
// GET api/values
public IEnumerable<Incident> Get()
{
using (EntityDemoEntities context = new EntityDemoEntities())
{
return context.Incidents.ToList<Incident>();
}
}
// GET api/values/5
public Incident Get(string id)
{
using (EntityDemoEntities context = new EntityDemoEntities())
{
Guid tempGuid = new Guid(id);
return context.Incidents.SingleOrDefault(i => i.IncidentId == tempGuid);
}
}
// PUT api/values/5
[HttpPut]
public void Put(string guid)
{
HttpResponseMessage result = new HttpResponseMessage();
try
{
if (ModelState.IsValid)
{
//Do something
}
else
{
result = Request.CreateResponse(HttpStatusCode.InternalServerError, "Invalid Model");
}
}
catch (Exception ex)
{
result = Request.CreateResponse(HttpStatusCode.InternalServerError, String.Format("{1}{0}{2}{0}{3}{0}{4}", Environment.NewLine, ex.Message, ex.StackTrace, ex.InnerException == null ? String.Empty : ex.InnerException.Message, ex.InnerException == null ? String.Empty : ex.InnerException.StackTrace));
}
}
}
}
WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Web.config
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name ="WebDAVModule"/>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<modules runAllManagedModulesForAllRequests="true">
<remove name='WebDAVModule'/>
</modules>
Change your action to Put(string id) or Put([FromUri(Name="id")]string guid)
I am currently implementing a Federated Authentication solution using:
A passive STS for issuing tokens, a Website hosting a Silverlight application and WCF services for the Silverlight App.
So far I am able:
Get redirected to the STS
Login and get redirected to the Website
Display the claims on the website by accessing
HttpContext.Current.User.Identity as IClaimsIdentity;
on the web.config of the Website, I have added the two WIF modules needed (under IIS 7)
<modules runAllManagedModulesForAllRequests="true">
<add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler"/>
<add name="SessionAuthenticationModule" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler"/>
</modules>
I have also configured the Microsoft.IdentityModel section of the web.config to use my own implementation of ClaimsAuthenticationManager and ClaimsAthorizationManager.
<service name="Rem.Ria.PatientModule.Web.WebService.PatientService">
<claimsAuthenticationManager type ="Rem.Infrastructure.WIF.RemClaimsAuthenticationManager"/>
<claimsAuthorizationManager type ="Rem.Infrastructure.WIF.RemClaimsAuthorizationManager"/>
</service>
My ClaimsAuthenticationMAnager is simply setting the Thread.CurrentPrincipal is a valid Principal is provided.
class RemClaimsAuthenticationManager : ClaimsAuthenticationManager
{
public override IClaimsPrincipal Authenticate ( string resourceName, IClaimsPrincipal incomingPrincipal )
{
if ( incomingPrincipal.Identity.IsAuthenticated )
{
Thread.CurrentPrincipal = incomingPrincipal;
}
return incomingPrincipal;
}
}
}
The problem is that when my ClaimsAuthorizationManager is called, the context.Principal.Identity does not contain a valid Identity with Claims, and neither does the Thread.CurrentPrincipal.
Any ideas?
You don't need to set the Thread.CurrentPrincipal because the session module will do this for you. You will need to access it through the HttpContext.Current.User because the Thread.Principal is usually set on a different thread than the one accessing your service because it is two different modules in IIS. We have an example of this in our upcoming book that you can check out at our Codeplex Site.
HTH
The following sample code shows a sample class which inherits ClaimsAuthenticationManager. It just receives the incoming IClaimsPrincipal and passes through the claims, except the Name claim, which is modified. This does not set the CurrentPrincipal on the current thread, as in your example.
My test implementation is as follows:
public class CustomClaimsAuthenticationManager : ClaimsAuthenticationManager
{
public CustomClaimsAuthenticationManager()
{
}
public override IClaimsPrincipal Authenticate(string resourceName,
IClaimsPrincipal incomingPrincipal)
{
var outgoingIdentity = GetClaimsAsPassthrough(incomingPrincipal);
return outgoingIdentity;
}
private IClaimsPrincipal GetClaimsAsPassthrough(IClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return incomingPrincipal;
}
var ingoingClaims = incomingPrincipal.Identity as IClaimsIdentity;
ClaimsIdentity outgoingIdentity = new ClaimsIdentity(new List<Claim>
{
new Claim(ClaimTypes.Name, (incomingPrincipal.Identity.Name + "
a very cool guy"))
}, incomingPrincipal.Identity.AuthenticationType);
foreach (var claim in ingoingClaims.Claims.Where(
c => c.ClaimType != ClaimTypes.Name))
{
outgoingIdentity.Claims.Add(claim.Copy());
}
return new ClaimsPrincipal(new List<ClaimsIdentity> { outgoingIdentity });
}
}