C# EWS in Exchange AutodiscoverUrl Exception while using Version 2010 or latest - exchange-server

a had successful connection with ExchangeVersion.Exchange2007_SP1, when I changed it on 2010 or latest I get the exception on this row:
service.AutodiscoverUrl(MailboxToAccess, RedirectionUrlValidationCallback);
->System.NullReferenceException: 'Object reference not set to an instance of an object.'
I tried with Packages:
Exchange.WebServices.Managed.Api v2.2.1.2 and Microsoft.Exchange.WebServices v2.2.0
static void Main(string[] args)
{
String MailboxToAccess = "username#domain";
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false);
service.Credentials = new WebCredential("username#domain", "password");
service.AutodiscoverUrl(MailboxToAccess, RedirectionUrlValidationCallback);
SetStreamingNotifications(service);
}
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}

I set the Exchange service URL manually using
/ Create the binding.
ExchangeService service = new ExchangeService();
// Set the credentials for the on-premises server.
service.Credentials = new WebCredentials("user1#contoso.com", "password");
// Set the URL.
service.Url = new Uri("https://computername.domain.contoso.com/EWS/Exchange.asmx");
I still don't understand why It didn't work for me with
service.AutodiscoverUrl("User1#contoso.com");

Related

Get Azure B2C User Directory listing in Azure Function with MSAL.NET

We are currently getting a list of our Users using MS Graph and the directoryObjects/getByIds endpoint.
In the Startup of the ASP NET Core API we are using Microsoft.IdentityModel.Clients.ActiveDirectory and this code
services.AddHttpClient("GraphApi", async hc =>
{
AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com/" + this.configuration["GraphApi:Tenant"]);
ClientCredential credential = new ClientCredential(this.configuration["GraphApi:ClientId"], this.configuration["GraphApi:ClientSecret"]);
hc.BaseAddress = new Uri($"https://graph.microsoft.com/v1.0/");
hc.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
AuthenticationResult result = await authContext.AcquireTokenAsync("https://graph.microsoft.com/", credential);
hc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
});
I am creating a new Azure Function and need to do the same thing again. I was going to use the same code and Microsoft.IdentityModel.Clients.ActiveDirectory but that package has been deprecated and we should be using Microsoft.Identity.Client.
I can see lots of samples for various scenarios but they seem to be all calling the public MS Graph whereas I want to get the users from our own Azure B2C. Can someone point me at the right resources\demo.
The Azure Function will not be running in the context of a user so Managed Identity or Client Secret approach would be useful
I have implemented a similar kind of scenario for getting Azure AD user but different way in MVC
CODE
I have used these NuGet packages
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
Startup class
public class Startup
{
string clientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"];
string redirectUri = System.Configuration.ConfigurationManager.AppSettings["RedirectUri"];
static string tenant = System.Configuration.ConfigurationManager.AppSettings["Tenant"];
string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture, System.Configuration.ConfigurationManager.AppSettings["Authority"], tenant);
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
RedirectUri = redirectUri,
PostLogoutRedirectUri = redirectUri,
Scope = OpenIdConnectScope.OpenIdProfile,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = false // This is a simplification
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed
},
}
);
}
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
context.HandleResponse();
context.Response.Redirect("/?errormessage=" + context.Exception.Message);
return Task.FromResult(0);
}
HomeController
public void SignIn()
{
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Authentication.Challenge( new AuthenticationProperties { RedirectUri = "/" }, OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
public void SignOut()
{
HttpContext.GetOwinContext().Authentication.SignOut( OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);
}
ClaimsController
public ActionResult Index()
{
var userClaims = User.Identity as System.Security.Claims.ClaimsIdentity;
ViewBag.Name = userClaims?.FindFirst("name")?.Value;
ViewBag.Username = userClaims?.FindFirst("preferred_username")?.Value;
ViewBag.Subject = userClaims?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
ViewBag.TenantId = userClaims?.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid")?.Value;
return View();
}
I tried to cover all possible implementations. Hope it will work in your case
Thanks

Crystal Report ExportToStream Failing with Object Reference not set to an instance

I have a very simple app that takes in No parameters in the attempt to return PDF.
The crystal Reports were authored using CR IX and I had to update the web service code to use Crystal Report for Visual studio 13. I am able to set parameters, as well as being able to login and verify that login credentials are correct.
public string TestReport()
{
try
{
var p = new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("Product", "03R95-01"),
new KeyValuePair<string, string>("Product_Rev", "E-V001")
};
var reportParameters = new ParameterField[2];
var rpt = InitializeReport("testReport", p);
var s = rpt.ExportToStream(ExportFormatType.PortableDocFormat);
return "Stream exists";
}
catch (Exception ex)
{
return $"{ex.Message}|{ex.StackTrace}";
}
}
The Initialize Report method is:
private ReportDocument InitializeReport(string svrId, string reportName, List<KeyValuePair<string, string>> parameters)
{
var uid = "userId";
var pwd = "pwd";
var svr = "serverId";
var db = "DBNAME";
var reportFolder = "c:\\CrystalTest\\ReportFolder";
var reportFile = Path.Combine(reportFolder, $"{reportName}.rpt");
var rpt = new ReportDocument
{
FileName = reportFile
};
rpt.Load(reportFile);
var conInfo = new ConnectionInfo
{
UserID = uid,
Password = pwd,
ServerName = svr,
DatabaseName = db
};
foreach (Table t in rpt.Database.Tables)
{
try
{
var loginInfo = t.LogOnInfo;
loginInfo.ConnectionInfo = conInfo;
t.ApplyLogOnInfo(loginInfo);
if(!t.TestConnectivity())
{
throw new Exception($"{t.Name} failed login");
}
}
catch (Exception ex)
{
throw;
}
}
rpt.VerifyDatabase();
return rpt;
}
I have verified that an error is thrown when userid/pass combinations are incorrect.
I get the following error when I run this.
Object reference not set to an instance of an object.| at
CrystalDecisions.CrystalReports.Engine.FormatEngine.ExportToStream(ExportRequestContext
reqContext) at
CrystalDecisions.CrystalReports.Engine.ReportDocument.ExportToStream(ExportOptions
options) at
CrystalDecisions.CrystalReports.Engine.ReportDocument.ExportToStream(ExportFormatType
formatType) at ICEWS4.maintenance.TestReport() in
C:\CrystalTest.cs:line 724
I learned of the fix.
I had CR for VS 13 SP 29.
The Runtime installed on the server was 13 SP 23
I was told by SAP to update to SP 30.
After updating my code, and installing the runtime, I was able to export to PDF as desired.

How to register a new user in ASP.NET MVC application by passing the data into a Web API?

In my ASP.NET MVC 5 application, I want to make the Admin User add a new user. Upon signing in, the registration form fields (registration view) with new user values are captured in AccountController of the ASP.NET MVC 5 application as follows, and which then calls the API and the data must be transferred there:
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult Register(AccountRegistration register)
{
string baseAddress = ConfigurationManager.AppSettings["ApiBaseUrl"];
//var client = new HttpClient();
//client.BaseAddress = new Uri("api/Account/Register");
//client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
string accessToken = this.ControllerContext.HttpContext.Request.Cookies["auth_key"].Values["token"];
using (var client = new HttpClient())
{
var form = new Dictionary<string, string>
{
{ "firstname", register.FirstName.Trim()},
{ "lastname", register.LastName.Trim()},
{ "email", register.Email.Trim()},
{ "phone", register.PhoneNo.Trim()},
{ "password", register.Password.Trim()},
};
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
var res = client.PostAsync(baseAddress + "/api/Account/Register", new StringContent(JsonConvert.SerializeObject(register), Encoding.UTF8, "application/json"));
res.Wait();
var taskResponse = res.Result;
var data = taskResponse.Content.ReadAsAsync<object>(new[] { new JsonMediaTypeFormatter() }).Result;
}
return View();
}
Here is my Web API AccountController code:
[HttpPost]
public IHttpActionResult Register([FromBody]UserRegister register)
{
DBAccess dblayer = new DBAccess();
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
UserManager<IdentityUser> _manager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(new TachusApi.DBContext.AuthDbContext()));
string pHash = _manager.PasswordHasher.HashPassword(register.Password);
dblayer.SaveAdmin(register, pHash);
return Ok("Success");
}
catch (Exception)
{
return Ok("Something went wrong.");
}
}
And here is the DBAccess.cs method which is called from this API's Register method to actually save the data into the database.
#region Save Admin
public void SaveAdmin(UserRegister user, string passwordHash)
{
SqlConnection conn = null;
SqlCommand command = null;
int retValue;
conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
command = conn.CreateCommand();
command.CommandText = "Sp_Add_Admin";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#Email", user.Email);
command.Parameters.AddWithValue("#PasswordHash", passwordHash);
command.Parameters.AddWithValue("#FirstName", user.FirstName);
command.Parameters.AddWithValue("#LastName", user.LastName);
command.Parameters.AddWithValue("#PhoneNumber", user.PhoneNumber);
conn.Open();
command.ExecuteNonQuery();
conn.Close();
}
#endregion
My problem is that I have all the values of Register.cshtml (User Registration View) available on both the Register and SaveAdmin methods of the API except the phone number. I think I have some ambiguity in the model classes that I have created. I want the data to be stored in the database using a stored procedure I created.
When I run the code and the API is called, I am getting exception. Is there any one who can suggest me the best way to manage my code so that I can save the data into the database?

Web API authentication on server

I am writing an Windows App that will communicate with Web API. Here is how I am making a call :
HttpClient client = null;
HttpClientHandler handler = new HttpClientHandler() { PreAuthenticate = true, Credentials = CredentialCache.DefaultCredentials };
client = new HttpClient();
client.BaseAddress = new Uri(apiBaseAddress);
var byteArray = Encoding.ASCII.GetBytes(Environment.UserName);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
HttpResponseMessage response = client.GetAsync("api/Tickets/AuthenticateUser").Result;
I am passing the currently logged credentials. I have written a filter which connects to db and checks if the username exists. The code :
public class BasicAuthenticationWindowsAppAttribute : System.Web.Http.Filters..AuthorizationFilterAttribute
{
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Authorization == null)
{
actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
else
{
string authToken = actionContext.Request.Headers.Authorization.Parameter;
string Handle = Encoding.UTF8.GetString(Convert.FromBase64String(authToken));
GenericIdentity gi = new GenericIdentity(Handle);
Thread.CurrentPrincipal = new GenericPrincipal(gi, null);
HttpContext.Current.User = Thread.CurrentPrincipal;
Amo_MasterDataEntities amoMasterDataContext = new Amo_MasterDataEntities();
var query = from a in amoMasterDataContext.allassociatemasters
where a.Handle == Handle
select a;
//If Handle is present in AMOMasterData.AllAssociatemaster table
if (query.Count() > 0)
{
//TicketsController tc = new TicketsController();
string assocId = "", fName ="", lName = "";
bool authenticated = false;
foreach (var item in query)
{
assocId = item.AssociateID;
fName = item.FirstName;
lName = item.LastName;
authenticated = true;
}
AuthInfo info = new AuthInfo();
info.AssociateId = assocId;
info.FirstName = fName;
info.LastName = lName;
info.IsAuthenticated = authenticated;
actionContext.Request.Properties.Add(new KeyValuePair<string, object>("AuthInfo", info));
base.OnAuthorization(actionContext);
}
//else return error
else
actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
}
}
When I run the web service in my local system it works. But when I deploy the web service on server it is giving me 401 Unauhorized Message.
I have enabled both Basic and Windows Authentication in IIS and Web.config contains <authentication mode="Windows" />
Edit :
I am able to access the Web API Methods from the server where I have deployed.
But When I am calling the Web API from a windows client on another Machine it is throwing 401 error.
Should I use CORS? If yes please let me know how?
Can anybody give me a solution for this.
I found the reason,..
I was not passing the handler to constructor of HttpClient that was the problem. So in above code replace :
client = new HttpClient();
with :
client = new HttpClient(handler);
Such a silly mistake. Sorry for the trouble.

Google Cloud C# API Never Callback

I'm using the below code to access my storage:
private static IConfigurableHttpClientInitializer GetInstalledApplicationCredentials()
{
string serviceAccountEmail = "xxxxxxxx";
X509Certificate2 certificate;
using (Stream stream = new FileStream(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", "path.p12"), FileMode.Open, FileAccess.Read))
{
using (MemoryStream ms = new MemoryStream())
{
stream.CopyTo(ms);
certificate = new X509Certificate2(ms.ToArray(), "notasecret", X509KeyStorageFlags.Exportable);
}
}
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] {
StorageService.Scope.DevstorageFullControl
},
}.FromCertificate(certificate));
return credential;
}
private static StorageService GetStoreageService()
{
var service = new StorageService(
new BaseClientService.Initializer()
{
HttpClientInitializer = GetInstalledApplicationCredentials(),
ApplicationName = "app"
}
);
return service;
}
public static byte[] DownloadAudio(string fileName)
{
var service = GetStoreageService();
var req = service.Objects.Get(bucketName, fileName);
var readobj = req.Execute();
var downloader = new MediaDownloader(service);
using (var ms = new MemoryStream())
{
downloader.Download(readobj.MediaLink, ms);
return ms.ToArray();
}
}
In the line var readobj = req.Execute(); my application just blocks and never give me a response. I already tried with JSON and with OAuth. the only difference is that with OAuth in the IIS Express it works but outside IIS Express it is not. Using P12 or JSON I have the problema both in IIS or IIS Express.
Any idea?
Thank you,
Murilo
Not sure if this is the problem but try
certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);

Resources