How to get username without domain - asp.net

In an aspx page I get the Windows username with the function Request.LogonUserIdentity.Name. This function returns a string in the format "domain\user".
Is there some function to only get the username, without resorting to the IndexOf and Substring, like this?
public static string StripDomain(string username)
{
int pos = username.IndexOf('\\');
return pos != -1 ? username.Substring(pos + 1) : username;
}

If you are using Windows Authentication.
This can simply be achieved by calling System.Environment.UserName which will give you the user name only.
If you want only the Domain name you can use System.Environment.UserDomainName

I don't believe so. I have got the username using these methods before-
var user = System.Web.HttpContext.Current.User;
var name = user.Identity.Name;
var slashIndex = name.IndexOf("\\");
return slashIndex > -1
? name.Substring(slashIndex + 1)
: name.Substring(0, name.IndexOf("#"));
or
var name = Request.LogonUserIdentity.Name;
var slashIndex = name.IndexOf("\\");
return slashIndex > -1
? name.Substring(slashIndex + 1)
: name.Substring(0, name.IndexOf("#"));

Getting parts[1] is not a safe approach. I would prefer use LINQ .Last():
WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
if (windowsIdentity == null)
throw new InvalidOperationException("WindowsIdentity is null");
string nameWithoutDomain = windowsIdentity.Name.Split('\\').Last();

If you are using .NET 3.5 you could always create an extension method to the WindowsIdentity class that does this work for you.
public static string NameWithoutDomain( this WindowsIdentity identity )
{
string[] parts = identity.Name.Split(new char[] { '\\' });
//highly recommend checking parts array for validity here
//prior to dereferencing
return parts[1];
}
that way all you have to do anywhere in your code is reference:
Request.LogonUserIdentity.NameWithoutDomain();

static class IdentityHelpers
{
public static string ShortName(this WindowsIdentity Identity)
{
if (null != Identity)
{
return Identity.Name.Split(new char[] {'\\'})[1];
}
return string.Empty;
}
}
If you include this code, you could then just do something like:
WindowsIdentity a = WindowsIdentity.GetCurrent();
Console.WriteLine(a.ShortName);
Obviously in a web environment, you wouldn't write to the console - just an example...

An alternative way of doing the same thing as the other answers:
var usernameWithoutDomain = Path.GetFileName(#"somedomain\someusername")
It is just unsafe as not checking for the # variant of usernames.

I was suggesting to use regexpes but they would be overkill.
[System.String.Split](http://msdn.microsoft.com/en-us/library/b873y76a(VS.80).aspx) do the job.
string[] parts= username.Split( new char[] {'\\'} );
return parts[1];

Related

Passing the servername/Ldap inside "DirectoryEntry" Vs "PrincipalContext"

I have this action method inside my ASP.NET MVC-5 .net 4.6:-
public ActionResult UsersInfo2()
{
List<DomainContext> results = new List<DomainContext>();
try
{
// create LDAP connection object
DirectoryEntry myLdapConnection = createDirectoryEntry();
string ADServerName = System.Web.Configuration.WebConfigurationManager.AppSettings["ADServerName"];
string ADusername = System.Web.Configuration.WebConfigurationManager.AppSettings["ADUserName"];
string ADpassword = System.Web.Configuration.WebConfigurationManager.AppSettings["ADPassword"];
using (var context = new DirectoryEntry("LDAP://mydomain.com:389/DC=mydomain,DC=com", ADusername, ADpassword))
using (var search = new DirectorySearcher(context))
{
SearchResult r = search.FindOne();
ResultPropertyCollection fields = r.Properties;
foreach (String ldapField in fields.PropertyNames)
string temp;
foreach (Object myCollection in fields[ldapField])
temp = String.Format("{0,-20} : {1}",
ldapField, myCollection.ToString());
}
}
using (var context = new PrincipalContext(ContextType.Domain, "mydomain.com", ADusername, ADpassword))
{
bool isvalid = context.ValidateCredentials("*******", "****************");
}
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return View(results);
}
so after around one day of testing i realize that for the DirectoryEntry I need to pass the server/ldap as follow ("LDAP://mydomain.com:389/DC=mydomain,DC=com", ADusername, ADpassword)) , while for the PrincipalContext we need to pass it as follow:- (ContextType.Domain, "mydomain.com", ADusername, ADpassword)).. so i can not pass the ldap inside the PrincipalContext nor the servrname only inside the DirectoryEntry .. so is this the case? or i am doing things wrongly ?
Thanks
You are correct.
The System.DirectoryServices.AccountManagement namespace (PrincipalContext, UserPrincipal, etc.) was created to simplify things. However, it just uses the System.DirectoryServices namespace (DirectoryEntry, etc.) in the background. (except for ValidateCredentials, which uses System.DirectoryServices.Protocols.LdapConnection).
I prefer to always use DirectoryEntry and friends because it gives me more control over performance. That's something I wrote an article about: Active Directory: Better performance

How can I get Cookie value by declare a Local variable in asp.net

When I Debug this line it shows like
Request.Cookies["Login"]["Username"].ToString()="Raju"
But when I declare a String type variable like
String ss;
ss = Request.Cookies["Login"]["Username"].ToString();
After debugging ss shows like
ss=null;
why?
public ActionResult Login()
{
UserAccount u = new UserAccount();
if (Request.Cookies["Login"] != null)
{
u.UserName = Request.Cookies["Login"].Values["UserName"];
}
return View(u);
}
You can define like this
String ss;
ss = Request.Cookies["Login"].Values["UserName"];

"Current user did not login to the application!" error when function call from service

In a service I have wrote a simple function to get tenant id of particular user
[AbpAuthorize]
public int? FindTenancyNameByUserNameOrEmail(string userNameOrEmail)
{
var qry = (from p in _memberRepository.GetAll()
where p.UserName == userNameOrEmail || p.EmailAddress == userNameOrEmail
select p).FirstOrDefault();
if (qry != null)
{
return qry.TenantId;
}
else
{
throw new Exception("User not found");
}
}
I am calling this function from login function of account controller.
public async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "", string returnUrlHash = "")
{
var tenancyid = _memberAppService.FindTenancyNameByUserNameOrEmail(loginModel.UsernameOrEmailAddress.Trim());
//bla bla code
}
I get following error:
Exception thrown: 'Abp.Authorization.AbpAuthorizationException' in
Abp.dll
Additional information: Current user did not login to the application!
The issue was the user was not belonging to the tenant.
Used the following line to set the tenant id and code worked.
CurrentUnitOfWork.SetFilterParameter(AbpDataFilters.MayHaveTenant, AbpDataFilters.Parameters.TenantId, intTenancyId);
added the [AbpAllowAnonymous] attribute to the service method
The problem is in first line
var qry = (from p in _memberRepository.GetAll()
.GetAll() function create this error as you cannot use Builtin function in linq query.
Instead use
var Myvariable = _memberRepository.GetAll().ToList();
var qry = (from p in Myvariable where p.UserName == userNameOrEmail || p.EmailAddress == userNameOrEmail select p).FirstOrDefault();
The problem is AbpAuthorize Attribute [AbpAuthorize] remove it.

Get Full name from Windows Authentication in ASP.Net BLL class

Trying to figure out how to get the current User's Full Name as entered in Active Directory from a BLL class in my ASP.Net application. So far I have:
public static string Username
{
get
{
var name = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
if (name.Contains("\\"))
{
var start = name.IndexOf("\\");
if (name.Length > start)
{
name = name.Substring(start + 1);
}
}
return name;
}
}
The problem with this is that this will return the Username, but I am also in need of the Full Name. Anyone know if this is possible?
Use a DirectorySearcher ...
var search = new DirectorySearcher( new DirectoryEntry("LDAP://YourDomain") );
search.Filter = "(sAMAccountName=UserNameHere)"; // put the identity name here
var res = search.FindOne();
var name = res["displayName"]; // I believe this is the right property

ASP.NET: URI handling

I'm writing a method which, let's say, given 1 and hello should return http://something.com/?something=1&hello=en.
I could hack this together pretty easily, but what abstraction functionality does ASP.NET 3.5 provide for building URIs? I'd like something like:
URI uri = new URI("~/Hello.aspx"); // E.g. ResolveUrl is used here
uri.QueryString.Set("something", "1");
uri.QueryString.Set("hello", "en");
return uri.ToString(); // /Hello.aspx?something=1&hello=en
I found the Uri class which sounds highly relevant, but I can't find anything which does the above really. Any ideas?
(For what it's worth, the order of the parameters doesn't matter to me.)
Edited to correct massively incorrect code
Based on this answer to a similar question you could easily do something like:
UriBuilder ub = new UriBuilder();
// You might want to take more care here, and set the host, scheme and port too
ub.Path = ResolveUrl("~/hello.aspx"); // Assumes we're on a page or control.
// Using var gets around internal nature of HttpValueCollection
var coll = HttpUtility.ParseQueryString(string.Empty);
coll["something"] = "1";
coll["hello"] = "en";
ub.Query = coll.ToString();
return ub.ToString();
// This returned the following on the VS development server:
// http://localhost/Hello.aspx?something=1&hello=en
This will also urlencode the collection, so:
coll["Something"] = "1";
coll["hello"] = "en&that";
Will output:
Something=1&hello=en%26that
As far I know nothing here. So everybody has its own implementation.
Example from LinqToTwitter.
internal static string BuildQueryString(IEnumerable<KeyValuePair<string, string>> parameters)
{
if (parameters == null)
{
throw new ArgumentNullException("parameters");
}
StringBuilder builder = new StringBuilder();
foreach (var pair in parameters.Where(p => !string.IsNullOrEmpty(p.Value)))
{
if (builder.Length > 0)
{
builder.Append("&");
}
builder.Append(Uri.EscapeDataString(pair.Key));
builder.Append("=");
builder.Append(Uri.EscapeDataString(pair.Value));
}
return builder.ToString();
}
UPDATE:
You can also create extension method:
public static UriBuilder AddArgument(this UriBuilder builder, string key, string value)
{
#region Contract
Contract.Requires(builder != null);
Contract.Requires(key != null);
Contract.Requires(value != null);
#endregion
var query = builder.Query;
if (query.Length > 0)
{
query = query.Substring(1) + "&";
}
query += Uri.EscapeDataString(key) + "="
+ Uri.EscapeDataString(value);
builder.Query = query;
return builder;
}
And usage:
var b = new UriBuilder();
b.AddArgument("test", "test");
Please note that everything here is untested.
Just combined answers=>
public static class UriBuilderExtensions
{
public static void AddQueryArgument(this UriBuilder b, string key, string value)
{
key = Uri.EscapeDataString(key);
value = Uri.EscapeDataString(value);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key)) throw new ArgumentNullException
("Key '{0}' already exists!".FormatWith(key));
x.Add(key, value);
b.Query = x.ToString();
}
public static void EditQueryArgument(this UriBuilder b, string key, string value)
{
key = Uri.EscapeDataString(key);
value = Uri.EscapeDataString(value);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key))
x[key] = value;
else throw new ArgumentNullException
("Key '{0}' does not exists!".FormatWith(key));
b.Query = x.ToString();
}
public static void AddOrEditQueryArgument(this UriBuilder b, string key, string value)
{
key = Uri.EscapeDataString(key);
value = Uri.EscapeDataString(value);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key))
x[key] = value;
else
x.Add(key, value);
b.Query = x.ToString();
}
public static void DeleteQueryArgument(this UriBuilder b, string key)
{
key = Uri.EscapeDataString(key);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key))
x.Remove(key);
b.Query = x.ToString();
}
}
Half baked code. But should work well enough.
There's also the UriBuilder class
This is something that might appeal to you- recently at work I was looking at a way to "type" commonly used URL query string variables and so developed this interface:
'Represent a named parameter that is passed from page-to-page via a range of methods- query strings, HTTP contexts, cookies, session, etc.
Public Interface INamedParam
'A key that uniquely identfies this parameter in any HTTP value collection (query string, context, session, etc.)
ReadOnly Property Key() As String
'The default value of the paramter.
ReadOnly Property DefaultValue() As Object
End Interface
You can then implement this interface to describe a query string parameter, such an implementation for your "Hello" param might look like this:
Public Class HelloParam
Implements INamedParam
Public ReadOnly Property DefaultValue() As Object Implements INamedParam.DefaultValue
Get
Return "0"
End Get
End Property
Public ReadOnly Property Key() As String Implements INamedParam.Key
Get
Return "hello"
End Get
End Property
End Class
I developed a small (and very, very basic) class to help build URLs using these strongly typed parameters:
Public Class ParametrizedHttpUrlBuilder
Private _RelativePath As String
Private _QueryString As String
Sub New(ByVal relativePath As String)
_RelativePath = relativePath
_QueryString = ""
End Sub
Public Sub AddQueryParameterValue(ByVal param As INamedParam, ByVal value As Object)
Dim sb As New Text.StringBuilder(30)
If _QueryString.Length > 0 Then
sb.Append("&")
End If
sb.AppendFormat("{0}={1}", param.Key, value.ToString())
_QueryString &= sb.ToString()
End Sub
Public Property RelativePath() As String
Get
Return _RelativePath
End Get
Set(ByVal value As String)
If value Is Nothing Then
_RelativePath = ""
End If
_RelativePath = value
End Set
End Property
Public ReadOnly Property Query() As String
Get
Return _QueryString
End Get
End Property
Public ReadOnly Property PathAndQuery() As String
Get
Return _RelativePath & "?" & _QueryString
End Get
End Property
End Class
Here's my version (needs .NET4 or a ToArray() call on the Select)
var items = new Dictionary<string,string> { { "Name", "Will" }, { "Age", "99" }};
String query = String.Join("&", items.Select(i => String.Concat(i.Key, "=", i.Value)));
I thought the use of Dictionary might mean the items can get reordered, but that doesn't actually seem to be happening in experiments here - not sure what that's about.

Resources