Hide a QueryString parameters, how? - c#

I have a url: like this one: http://www.example/about/49.
I want it to be seen as http://www.example/about/, but I must have this parameters passed as QueryString parameters.
Is it possible ?

Be careful with session variables; it's easy to have multiple pages opened which are all using the same session and end up mixing the values.
It would be better to use TempData, which only allows the value to be used once (removed on first access). However, this implies the value will be used almost immediately.
You can also write a cookie with the desired value, intercept the request (ASP.Net provides a variety of ways of doing this, such as the BeginRequest event), and internally process the URL as though it contained the value.
Of course, you then must cleanup the cookie (which will have the same problem as a Session-based solution). Remember that a cookie is more vulnerable to tampering on the client.
Personally, I think any of these approaches are far more trouble than they are worth. "Hackable URLs" (such as those which contain a potentially meaningful ID) are usually a good thing.

My workaround for this (Which works REALLY well, thanks to the help of the SO Community)
Create a class called SiteSession.cs
Input the following code:
using System;
using System.Collections.Generic;
using System.Web;
/// <summary>
/// Summary description for SiteSession
/// </summary>
public class SiteSession
{
/// <summary>
/// The _site session
/// </summary>
private const string _siteSession = "__SiteSession__";
/// <summary>
/// Prevents a default instance of the <see cref="SiteSession" /> class from being created.
/// </summary>
private SiteSession()
{
}
/// <summary>
/// Gets the current Session
/// </summary>
/// <value>The current.</value>
public static SiteSession Current
{
get
{
SiteSession session = new SiteSession();
try
{
session = HttpContext.Current.Session[_siteSession] as SiteSession;
}
catch(NullReferenceException asp)
{
}
if (session == null)
{
session = new SiteSession();
HttpContext.Current.Session[_siteSession] = session;
}
return session;
}
}
//Session properties
public int PageNumber {get;set;}
}
You can put anything in the Session Properties, just make sure its public.
Then, set it by:
SiteSession.Current.PageNumber = 42
And call it with
int whatever = SiteSession.Current.PageNumber

Related

What is the proper return type for an C# SDK CRUD operations?

I'm currently struggling to write a really good SDK for our API. I'm looking at doing it one of a few ways right now.
I can either pass the HttpResponseMessage back from my API call (as you can see below).
I can do some data processing and pass back just the object.
I can create a custom object to wrap the SDK return so that it can contain what it needs to.
I can throw exceptions when a server error is encountered, but that can be expensive especially if the application can recover from the exception.
I could also return a tuple in the getter here so that I get both an object and the HttpResponseMessage.
I want the SDK to do just the right amount of processing on the data and I'm not sure if there is an example of how to write a good SDK in .NET or not. I am actually going to consume this SDK myself so I want it to be good. I have written some code and I'll include that here but I think it's current iteration is flawed.
public interface IBaseApi<T>
{
Task<IEnumerable<T>> GetAllAsync();
Task<T> GetByIdAsync(int id);
Task<HttpResponseMessage> InsertAsync(T obj);
Task<HttpResponseMessage> UpdateAsync(T obj);
Task<HttpResponseMessage> DeleteAsync(int id);
}
Right now we return a null object to indicate that either Get request failed. But I think that's a flawed concept.
I've also looked at the Facebook, Square, and a few other Sdks. Nothing quite hit the mark for me.
So what return type should my API be sending? Just a pointer, I don't know how the client is going to consume this. It could be part of a larger query or a direct pass through to their Controller. My overall goal is that the consumer will have as little processing to do themselves, but also a meaningful if something goes wrong message.
What I have done in the past and has worked really well is to create an "Api Response" object that contains metadata about the response as well as the actual data resulting from the call, something along the lines of:
public class ApiResponse<TData>
{
/// <summary>
/// Constructor for success.
/// </summary>
/// <param name="data"></param>
public ApiResponse(TData data)
{
Data = data;
Success = true;
Errors = new List<string>();
}
/// <summary>
/// Constructor for failure.
/// </summary>
/// <param name="ex"></param>
public ApiResponse(IEnumerable<string> errors)
{
Errors = errors;
Success = false;
}
/// <summary>
/// Gets whether the API call was successful.
/// </summary>
public bool Success { get; private set; }
/// <summary>
/// Gets any errors encountered if the call was not successful.
/// </summary>
public IEnumerable<string> Errors { get; private set; }
/// <summary>
/// Gets the data resulting from the API call.
/// </summary>
public TData Data { get; private set; }
}
You could have a base class that does not return any data too and then derive this one from that.

autofac and owned instances

I have been reasing about owned instances and I have a need to set one up.
http://docs.autofac.org/en/latest/advanced/owned-instances.html
I have 2 methods in the same class that use this owned instance. I have set it up like this:
private readonly Func<SessionDetails, Owned<ITroposUnitOfWork>> _paramatizedTroposUnitOfWork;
My unit of work class constructor looks like this:
/// <summary>
/// Used for creating manual sessions
/// </summary>
/// <param name="sessionDetails">The details of the session to be created</param>
public TroposUnitOfWork(SessionDetails sessionDetails)
{
// Throw if we don't supply any details
ThrowIf.ArgumentIsNull(() => sessionDetails);
// Start the session
StartSession(sessionDetails);
}
So, my understanding is that if I use a using block, then the unit of work will be disposed of at the end of the call. But it isn't.
Like I mentioned before, I have 2 methods that use this owned instance. They are:
/// <summary>
/// Creates the Tropos user
/// </summary>
/// <param name="model">The user to be created</param>
/// <param name="password">The password to set</param>
private async Task CreateTroposUserAsync(User model, string password)
{
// If there is no password, throw an error
ThrowIf.ArgumentIsNull(() => password);
// Get our master user
var user = await base.FindByNameAsync(model.Master);
// If we have no master user, throw an error
if (user == null) throw new ObjectNotFoundException();
// Create our session details
var sessionDetails = _troposSession.Value.Create(user);
// User our new user
using (var troposUnitOfWork = _paramatizedTroposUnitOfWork(sessionDetails))
{
try
{
// Create our tropos user service
var userService = new TroposUserService(troposUnitOfWork.Value);
// Create our user
var transaction = userService.Create(model);
// Save our changes (Don't throw an error if the user already exists)
troposUnitOfWork.Value.RunTransaction(transaction);
} catch (Exception ex)
{
// Display human readable messages
throw new Exception(ex.Message);
}
}
// Sets the new users password
SetTroposPassword(model, password);
// Update the flag
model.HasTroposLogin = true;
}
And the other one is:
/// <summary>
/// Sets the tropos password
/// </summary>
/// <param name="model">The user that needs the password setting</param>
/// <param name="password"></param>
private void SetTroposPassword(User model, string password)
{
// Create our session details
var sessionDetails = _troposSession.Value.Create(model.UserName);
// Create our anonymous session
using (var troposUnitOfWork = _paramatizedTroposUnitOfWork(sessionDetails))
{
// Create our tropos user service
var userService = new TroposUserService(troposUnitOfWork.Value);
// Set our password
var transaction = userService.ChangePassword(password);
// Save our changes
troposUnitOfWork.Value.RunTransaction(transaction);
}
}
The first method does invoke the second method, but outside the using block. I put a breakpoint in the TroposUnitOfWork dispose method and it only gets hit once. The constructor is only hit once too.
Does anyone know why?
We need to see the initialization of _paramatizedTroposUnitOfWork.
What class has the CreateTroposUserAsync method? We need to see the constructor of that class. I suppose your overall goal is to get a unit of work implementation.
The reason why you only hit constructor once, might be due to the lifetime you used when registering. If its Owned. Then the two methods probably execute in the same lifetime scope and the dependency is only resolved once. Or put differently the _paramatizedTroposUnitOfWork(sessionDetails) returns the same instance.
I've solved similar problem using decorators and factories
public interface IEventHandlerFactory<in TNotification> where TNotification
: class, IAsyncNotification
{
IAsyncNotificationHandler<TNotification> Create( ILifetimeScope
lifetimeScope );
}
public class EventHandlerFactory<TNotification, TEventHandler> :
IEventHandlerFactory<TNotification>
where TNotification : class, IAsyncNotification
where TEventHandler : class, IAsyncNotificationHandler<TNotification>
{
public IAsyncNotificationHandler<TNotification> Create( ILifetimeScope
lifetimeScope )
{
return lifetimeScope.ResolveNamed<TEventHandler>( "EventHandler" )
as IAsyncNotificationHandler<TNotification>;
}
}
full .net fiddle is here https://dotnetfiddle.net/fw4IBw

Reference to an ASMX webservice wants to implement IDisposable

I have a somewhat simple web app, that uses an ASMX web service as its sole data access. All the information is gotten from it, and saved to it. It works fine so thats out of the way.
I just updated to VS2012, and it complained about the class implementing the service reference, does not inherit from IDisposeable.
After some reading, i am more confused as some solutions are really elaborate, some are simple. Short version is, after understanding so little, it seems like i cant adapt it to how my app is made.
I have several data access classes, all focusing on methods for an area. For example, one dataaccess for customer related calls, one for product related calls etc.
But since they are all using the same service, they all derive from a base data access class that holds the reference.
This is the base data access class:
public class BaseDataAccess
{
private dk.odknet.webudv.WebService1 _service;
private string _systemBrugerID, _systemPassword;
public BaseDataAccess()
{
//Gets the system user and password that is stored in the webconfig file. This means you only have to change
//the username and password in one place without having to change the code = its not hardcoded.
_systemBrugerID = System.Configuration.ConfigurationManager.AppSettings["SystemBrugerID"].ToString();
_systemPassword = System.Configuration.ConfigurationManager.AppSettings["SystemPassword"].ToString();
_service = new dk.odknet.webudv.WebService1();
}
/// <summary>
/// Gets an instance of the webservice.
/// </summary>
protected dk.odknet.webudv.WebService1 Service
{
get { return _service; }
}
/// <summary>
/// Gets the system user id, used for certain methods in the webservice.
/// </summary>
protected string SystemBrugerID
{
get { return _systemBrugerID; }
}
/// <summary>
/// Gets the system user password, used for certain methods in the webservice.
/// </summary>
protected string SystemPassword
{
get { return _systemPassword; }
}
}
And here is how a derived class utilizes the service reference from the base class:
public class CustomerDataAccess : BaseDataAccess
{
public CustomerDataAccess() {}
/// <summary>
/// Get's a single customer by their ID, as the type "Kunde".
/// </summary>
/// <param name="userId">The user's username.</param>
/// <param name="customerId">Customer's "fkKundeNr".</param>
/// <returns>Returns a single customer based on their ID, as the type "Kunde".</returns>
public dk.odknet.webudv.Kunde GetCustomerById(string userId, string customerId)
{
try
{
return Service.GetKunde(SystemBrugerID, SystemPassword, userId, customerId);
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}}
So how on earth do i implement IDisposable in this situation? I just cant wrap my head around it.
EDIT
I have fiddled with the service reference, and come up with this:
/// <summary>
/// Gets an instance of the webservice.
/// </summary>
protected dk.odknet.webudv.WebService1 Service
{
get
{
try
{
using (_service = new dk.odknet.webudv.WebService1())
{
return _service;
}
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}
}
Yes the exception handling isnt great, i will get to that (advice is appreciated), but VS2012 does not complain about the lack of IDisposable anymore.
Instantiation of the service has been removed from the constructor. The app works fine without any further modifications.
Will this suffice?

Reporting on code execution and design patterns?

First of all I wanted to thank all of you for your continuous contributions to the Stack Overflow community! I've been a member of Stack Overflow for years and have come to rely on your input more so than any other source online. Though I try to participate and answer members' questions whenever I can, every once in a while I find myself stuck and in need of help.
Speaking of which I have an unusual code problem. I am writing an API library in C# that needs to be able to be called from WPF/Windows Forms application, but also from within Unit Test code.
The issue is that I need to be able to report (in Excel) on whether each method of the library executed properly when the API is called from within a WPF/windows forms application, along some other metadata and optionally a return type.
When the code is consumed within Unit Tests I don't really care about the reporting, but I do need to be able to produce an Assert on whether the API call executed properly or not.
For instance, if in a Unit Test we have an Test Initialize portion, one of the API calls may be to create a Domain User for the test method to use. Another one may also create a Domain Group, so that the user has proper group membership.
To accomodate the consumption of the API from WPF/WinForms, I've been rewriting every function in the API to return a OperationStep type, with the hopes that when all API calls have executed I would have an IEnumerable<OperationStep> which I can write to a CSV file.
So the question is is there an easier way of achieving what I have done so far? The reporting is extremely tedious and time consuming to code, considering that the API library consists of hundreds of similar methods. Samples are described bellow:
OperationStep<PrincipalContext> createDomainConnectionStep = DomainContext.Current.GetPrincipalContext(settings.DomainInfo);
OperationStep<UserPrincipal> createDomainUserStep = DomainContext.Current.CreateUser(createDomainConnectionStep.Context, settings.TestAccountInfo.Username, settings.TestAccountInfo.Password);
OperationStep<GroupPrincipal> createDomainGroupStep = DomainContext.Current.CreateGroup(createDomainConnectionStep.Context, settings.TestAccountInfo.UserGrupName);
Where the DomainContext is a singleton object whose functionality is to connect to the domain controller and create a user, group, and associate the user to a group.
Note that both the second and the third method call require the output of the first, and therefore warranting the need for having the public T Context within the OperationResult object as described bellow.
The OperationStep object consists of the following properties which are inherited by the IOperation interface with the exception of the public T Context.
public class OperationStep<T> : IOperation
{
/// <summary>
/// Denotes the Logical Name of the current operation
/// </summary>
public string Name { get; set; }
/// <summary>
/// Denotes the stage of execution of the current operation: Setup, Execution, Validation, Cleanup
/// </summary>
public OperationStage Stage { get; set; }
/// <summary>
/// Denotes whether the test step completed properly or failed.
/// </summary>
public OperationResult Result { get; set; }
/// <summary>
/// Denotes the return type of the test method.
/// </summary>
public T Context { get; set; }
/// <summary>
/// Denotes any other relevant information about the test step
/// </summary>
public string Description { get; set; }
/// <summary>
/// If the test step result is failed, this should have the stack trace and the error message.
/// </summary>
public string Error { get; set; }
}
The method calls themselves are a bit bloated and tedious but here is a sample.
public class DomainContext
{
private static volatile DomainContext currentContext;
private static object synchronizationToken = new object();
/// <summary>
/// default ctor.
/// </summary>
private DomainContext() { }
/// <summary>
/// Retrieves the Current DomainContext instance.
/// </summary>
public static DomainContext Current
{
get
{
if (currentContext == null)
{
lock (synchronizationToken)
{
if (currentContext == null)
{
currentContext = new DomainContext();
}
}
}
return currentContext;
}
}
/// <summary>
/// Establishes a connection to the domain.
/// </summary>
/// <param name="domainInfo"></param>
/// <returns></returns>
public OperationStep<PrincipalContext> GetPrincipalContext(DomainInfo domainInfo)
{
OperationStep<PrincipalContext> result = new OperationStep<PrincipalContext>();
result.Name = "Establish Connection to Active Directory";
result.Result = OperationResult.Success;
result.Stage = OperationStage.Setup;
result.Description = string.Format("Domain Name: {0}, Default Containter: {1}", domainInfo.FQDN, domainInfo.Container);
try
{
ContextType contextType = this.GetContextType(domainInfo.DomainType);
PrincipalContext principalContext;
try
{
principalContext = new PrincipalContext(contextType, domainInfo.FQDN, domainInfo.Container);
}
catch
{
throw new Exception("Unable to establish connection to Active Directory with the specified connection options.");
}
if (principalContext != null)
{
bool authenticationResult = principalContext.ValidateCredentials(domainInfo.Username, domainInfo.Password);
if (!authenticationResult)
{
throw new Exception("Unable to authenticate domain admin user to Active Directory.");
}
result.Context = principalContext;
result.Result = OperationResult.Success;
}
}
catch(Exception ex)
{
result.Error = ex.Message;
result.Result = OperationResult.Failure;
}
return result;
}
}
When all method calls have executed theoreticaly I should have an IEnumerable<IOperation> which in the case of a win form I can write in a csv file (to be viewed in MS Excel) or in the case of a unit test I can simply omit the extra info and ignore (other than the method executed successively and the T Context property).
If I understood you correctly - all that OperationSteps are here only for logging. Then why not enable simple .NET logging? Log needed info where it is convenient for you. You can use TraceSource with DelimetedTraceListener to write to .csv file. More than that. You can move logging logic to Strategy class and override its logging methods in your unit test so that instead of logging you call Assert methods.

What mistake could cause error: A required anti-forgery token was not supplied or was invalid

My question is very similar to this issue: AntiForgery Exception: A required anti-forgery token was not supplied or was invalid
but I have the MVC3 and I using Razor installed.
controller has the
[ValidateAntiForgeryToken]
specified
in html is printed <input name="__RequestVerificationToken"... using #Html.AntiForgeryToken()
Also I observed, that if I remove the Authorization cookie in the browser, and controller method does not have [Authorize] I don't have any problems with AntiForery. Why?
Check your cookies and make sure that you are seeing the requestVerificationToken cookie being set correctly. I have run into this before where the cookies for the site were all set to be SSL only and I was trying to run it over regular HTTP locally, so the cookie was never being accepted because it was being transmitted over unsecure channels.
For me, this meant changing a line in the web.config under system.web/httpCookies to requireSSL="false"... but if this isn't what you are seeing, I would still look at things that might be messing with your cookies in the system (e.g. session resets, manually clearing the cookies somewhere, etc.). If you have the validation attribute on the controller methods correctly, and are still getting this, it is likely due to something modifying or removing that cookie!
Edit: Also, if you have this on the controller instead of only on the POST methods, that would be why... This is only applicable to form POSTs to the server.
Here's a simple custom version that you CAN apply to the form that will automatically validate on ALL POST action methods:
/// <summary>
/// Custom Implementation of the Validate Anti Forgery Token Attribute.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CustomValidateAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
/// <summary>
/// The ValidateAntiForgeryTokenAttribute.
/// </summary>
private readonly ValidateAntiForgeryTokenAttribute _validator;
/// <summary>
/// The AcceptVerbsAttribute.
/// </summary>
private readonly AcceptVerbsAttribute _verbs;
/// <summary>
/// Initializes a new instance of the <see cref="CustomValidateAntiForgeryTokenAttribute"/> class.
/// </summary>
/// <param name="verbs">The verbs.</param>
public CustomValidateAntiForgeryTokenAttribute(HttpVerbs verbs) : this(verbs, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="CustomValidateAntiForgeryTokenAttribute"/> class.
/// </summary>
/// <param name="verbs">The verbs.</param>
/// <param name="salt">The salt.</param>
public CustomValidateAntiForgeryTokenAttribute(HttpVerbs verbs, string salt)
{
_verbs = new AcceptVerbsAttribute(verbs);
_validator = new ValidateAntiForgeryTokenAttribute
{
Salt = salt
};
}
/// <summary>
/// Called when authorization is required.
/// </summary>
/// <param name="filterContext">The filter context.</param>
public void OnAuthorization(AuthorizationContext filterContext)
{
var httpMethodOverride = filterContext.HttpContext.Request.GetHttpMethodOverride();
var found = false;
foreach (var verb in _verbs.Verbs)
{
if (verb.Equals(httpMethodOverride, StringComparison.OrdinalIgnoreCase))
{
found = true;
}
}
if (found && !filterContext.RequestContext.RouteData.Values["action"].ToString().StartsWith("Json"))
{
_validator.OnAuthorization(filterContext);
}
}
}
Then you can just add the following to all of your controllers, or to your base controller if you override and inherit from one:
[CustomValidateAntiForgeryToken(HttpVerbs.Post)]
Anti forgery token is tied to the user identity. If you changing currently logged in user identity between generating and validating tokens then token will not be validated successfully. Also, that explains why everything is working for you in anonymous mode.

Categories

Resources