How to connect couchDB with ASP.NET C# application? If any one can you give a sample application.
I had the same need and after evaluating the options available, to meet the requirements of my application, I created any components that helped me a lot and maybe they can help you and also others. I make it clear that I have no intention of promoting myself here, just sharing something that may be useful.
The detailed explanation of how to configure and use it is on Github.
Link: Nuget Package |
Github
Example of use for retrieving documents with mango-querie:
IList<User> users;
var sts = new List<String> { "ACTIVE", "LOCKED" };
using (UserRepository db = new UserRepository())
{
var query = db.FindOf("list-status", new { id = "OwnerIdloop.user.7", statuses = sts });
users = db.List<User>(query);
}
Array.ForEach(users.ToArray(), Console.WriteLine);
Example of adding documents:
User user = createUser("email#email.com");
using (UserRepository db = new UserRepository())
{
var result = db.Insert<User>(user); // add document and return instance changed with operation revision id
Console.WriteLine(result.Revision);
}
Example of changing documents:
using (UserRepository db = new UserRepository())
{
// Load document data by ID
var user = db.Get<User>("email#email.com");
user.Name = user.Name + "::CHANGED";
var result = db.Update<User>(user); // update document and return instance changed with operation revision id
Console.WriteLine(result.Revision);
}
Example of deleting documents:
using (UserRepository db = new UserRepository())
{
// Load document data by ID
var user = db.Get<User>("email#email.com");
var result = db.Delete<User>(user); // delete document from database. Return true case sucess or false case not deleted
Console.WriteLine($"Sucesso: {result}");
}
After installing the NuGet, just create an instance of MyCouch.Client and pass it the URL of your database.
using (var client = new MyCouchClient("http://127.0.0.1:5984/test"))
{
//Consume here
}
The format is: {scheme}://[{username}:{password}]/{authority}/{localpath}. From v0.11.0, there's a specific MyCouchUriBuilder that you can use for building the Uri. It will automatically e.g. apply Uri.EscapeDataString to username and password when calling SetBasicCredentials.
var uriBuilder = new MyCouchUriBuilder("http://localhost:5984/")
.SetDbName(TestConstants.TestDbName)
.SetBasicCredentials("foob#r", "p#ssword");
return new MyCouchClient(uriBuilder.Build());
For more details Click Here
Related
I want to link the existing work items which are already created in a project under Azure DevOps by writing a code or program in C#, so is there any kind of API or SDK which can be used to link the work items programmatically?
The Workitems can be of any type i.e.
Bug
User Story
Issue
Task etc.
The linking between the Workitems can also be of any type i.e. Relational, Parent-Child, etc.
Recently I referred to this link for my problem.
The link contains issue very much related and similar to mine, however it is not working as expected when I tried it.
Given:
//int relatedId = ...
//int id = ...
//CancellationToken token = ...
//string organization = ...
//string projectName = ...
//WorkItemTrackingHttpClient azureClient = ...
Create a JsonPatchDocument as below:
JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Add(
new JsonPatchOperation
{
From = null,
Operation = Operation.Add,
Path = "/relations/-",
Value = new {
rel = "System.LinkTypes.Related",
url = $"https://dev.azure.com/{organization}/{projectName}/_workitems/edit/{relatedId}",
attributes = new
{
comment = $"Created programmatically on {DateTime.Now}."
}
}
}
);
and call this async method of Azure DevOps SDK:
await azureClient.UpdateWorkItemAsync(patchDoc, id, false, true, true, WorkItemExpand.All, cancellationToken: token);
In the case above we created a related link using System.LinkTypes.Related referenceName.
For a full link types reference guide in Azure DevOps refer to this so's question or this microsoft's doc.
Using the Azure DevOps REST API in C#, I'm creating a pull request and then attempting to complete it like this (simplified):
var pullRequest = new GitPullRequest {
Title = "My PR",
SourceRefName = "refs/heads/my",
TargetRefName = "refs/heads/master",
Commits = commits
};
pullRequest = await gitClient.CreatePullRequestAsync(pullRequest, repositoryId);
await Task.Delay(3000);
if (pullRequest.MergeStatus == PullRequestAsyncStatus.Succeeded) {
var pr2 = new GitPullRequest
{
LastMergeSourceCommit = pullRequest.LastMergeSourceCommit,
Status = PullRequestStatus.Completed
};
var result = await gitClient.UpdatePullRequestAsync(pullRequest, pullRequest.Repository.Id, pullRequest.pullRequestId);
}
This works fine if there's no conflicts. But if the pull request has conflicts, MergeStatus will be Conflicts. Now, let's assume someone resolves those conflicts manually and the PR is ready to be merged.
After resolving conflicts I get the pull request again
var pullRequest = await gitClient.GetPullRequestByIdAsync(pullRequestId);
pullRequest.MergeStatus is still Conflicts, even though UI is showing green.
Is there a way to refresh MergeStatus once it has been set to Conflicts? I tried updating the pull request by setting MergeStatus to Queued. Or is it a missing feature in the API?
Hopefully you got through this, so just in case someone else comes looking (like I did today) this worked for me.
var prOriginal = gitClient.CreatePullRequestAsync(
new GitPullRequest() {
SourceRefName = $"refs/heads/{Input.SrcBranch}",
TargetRefName = $"refs/heads/{Input.TgtBranch}",
Title = Input.Title,
Description = Input.Description
},
tgtRepo.Id).Result;
Thread.Sleep(TimeSpan.FromSeconds(30));
var statusRetry = 0;
var prTest = gitClient.GetPullRequestAsync(
tgtRepo.Id,
prOriginal.PullRequestId).Result;
while(PullRequestAsyncStatus.Succeeded != prTest.MergeStatus) {
// TODO decide when to quit.
Thread.Sleep(TimeSpan.FromSeconds(30));
prTest = gitClient.GetPullRequestAsync(
tgtRepo.Id,
prOriginal.PullRequestId).Result;
}
Debug.WriteLine($"MergeStatus: {prTest.MergeStatus}");
MergeStatus came back succeeded soon after I resolved the problems online. Now if I can get those conflicts resolved using the api I'll be in great shape.
The story is: I am building a Node application, but I need data from Google AdWords. Since there is no official Node library and I couldn't get the unofficial ones to work I wanted to create a REST API in ASP.NET. So far this is what I have:
[HttpGet]
public IEnumerable<string> Get()
{
TargetingIdeaSelector selector = new TargetingIdeaSelector
{
requestType = RequestType.IDEAS,
ideaType = IdeaType.KEYWORD,
requestedAttributeTypes = new AttributeType[] {
AttributeType.KEYWORD_TEXT,
AttributeType.SEARCH_VOLUME,
AttributeType.AVERAGE_CPC,
AttributeType.COMPETITION,
AttributeType.CATEGORY_PRODUCTS_AND_SERVICES
}
};
// Set selector paging (required for targeting idea service).
Paging paging = Paging.Default;
// Create related to query search parameter.
RelatedToQuerySearchParameter relatedToQuerySearchParameter =
new RelatedToQuerySearchParameter
{
queries = new String[] {
"bakery", "pastries", "birthday cake"
}
};
var searchParameters = new List<SearchParameter>
{
relatedToQuerySearchParameter
};
TargetingIdeaPage page = new TargetingIdeaPage();
page = targetingIdeaService.get(selector);
return new string[] { "value1", "value2" };
}
I basically grabbed the code from the docs. The problem is that the targetingIdeaService is not defined. If I try to take a look at a code sample it looks like this:
public void Run(AdWordsUser user, long? adGroupId) {
using (TargetingIdeaService targetingIdeaService =
(TargetingIdeaService) user.GetService(AdWordsService.v201802.TargetingIdeaService)) {
// Create selector.
TargetingIdeaSelector selector = new TargetingIdeaSelector();
selector.requestType = RequestType.IDEAS;
selector.ideaType = IdeaType.KEYWORD;
selector.requestedAttributeTypes = new AttributeType[] {
AttributeType.KEYWORD_TEXT,
AttributeType.SEARCH_VOLUME,
AttributeType.AVERAGE_CPC,
AttributeType.COMPETITION,
AttributeType.CATEGORY_PRODUCTS_AND_SERVICES
};
List<SearchParameter> searchParameters = new List<SearchParameter>();
// Create related to query search parameter.
RelatedToQuerySearchParameter relatedToQuerySearchParameter =
new RelatedToQuerySearchParameter();
relatedToQuerySearchParameter.queries = new String[] {
"bakery", "pastries", "birthday cake"
};
searchParameters.Add(relatedToQuerySearchParameter);
And a lot more code. The point is they made it in a function, and are passing a user object into it. Now I will not have said object. Unless it's needed. Then I'm screwed. But I need to get this service up and running. This is the only missing step, other than that it should work.
So my question is: Does anyone see a way around it?
The AdWordsUser object contains the authentication you need to connect to the API. Without it your app will have no idea of which AdWords account and OAuth refresh token to supply to the TargetingIdeaService.
Sometimes users get Invalid Token when clicking on their email confirmation link. I can't figure out why, it's purely random.
Here is the code that creates the user:
IdentityResult result = manager.Create(user, "Password134567");
if (result.Succeeded)
{
var provider = new DpapiDataProtectionProvider("WebApp2015");
UserManager<User> userManager = new UserManager<User>(new UserStore<User>());
userManager.UserTokenProvider = new DataProtectorTokenProvider<User>(provider.Create(user.Id));
manager.UserTokenProvider = new DataProtectorTokenProvider<User>(provider.Create("ConfirmUser"));
var emailInfo = new Email();
string code = HttpUtility.UrlEncode(Context.GetOwinContext().GetUserManager<ApplicationUserManager>().GenerateEmailConfirmationToken(user.Id));
string callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request);
if (email.IndexOf("#") != -1)
{
if (assignedId == 0)
{
lblError.Text = "There was an error adding this user";
return;
}
string emailcontent = emailInfo.GetActivationEmailContent(assignedId, callbackUrl, userRole);
string subject = emailInfo.Subject;
if (string.IsNullOrEmpty(subject))
{
subject = "Your Membership";
}
Context.GetOwinContext()
.GetUserManager<ApplicationUserManager>()
.SendEmail(user.Id, subject, emailcontent);
if (user.EmailConfirmed)
{
IdentityModels.IdentityHelper.SignIn(manager, user, isPersistent: false);
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
}
else
{
ErrorMessage.ForeColor = Color.Green;
ErrorMessage.Text = "An email has been sent to the user, once they verify their email they are ready to login.";
}
}
else
{
ErrorMessage.ForeColor = System.Drawing.Color.Green;
ErrorMessage.Text = "User has been created.";
}
var ra = new RoleActions();
ra.AddUserToRoll(txtEmail.Text, txtEmail.Text, userRole);
}
else
{
ErrorMessage.Text = result.Errors.FirstOrDefault();
}
Here is the confirmation page that gives the 'invalid token' error
protected void Page_Load(object sender, EventArgs e)
{
var code = IdentityHelper.GetCodeFromRequest(Request);
var userId = IdentityHelper.GetUserIdFromRequest(Request);
if (code != null && userId != null)
{
var manager = Context.GetOwinContext()
.GetUserManager<ApplicationUserManager>();
var confirmId = manager.FindById(userId);
if (confirmId != null)
{
var result = manager.ConfirmEmail(userId, HttpUtility.UrlDecode(code));
if (result.Succeeded)
{
return;
}
else
{
lblError.Text = result.Errors.FirstOrDefault();
txtNewPassword.TextMode= TextBoxMode.SingleLine;
txtNewPassword.Text = "Error contact support";
txtNewPassword2.TextMode= TextBoxMode.SingleLine;
txtNewPassword2.Text = result.Errors.FirstOrDefault();
txtNewPassword.Enabled = false;
txtNewPassword2.Enabled = false;
imageButton1.Enabled = false;
}
}
else
{
lblError.Text = "Account Does Not Exist";
imageButton1.Enabled = false;
}
}
}
Live Demo Project
I've created a pared-down demo project for you. It's hosted on GitHub here and is live on Azure here. It works as designed (see edits about Azure Websites) and uses a similar but not identical approach as you used.
It started with this tutorial, and then I removed the cruft that came with this NuGet demo code:
Install-Package -Prerelease Microsoft.AspNet.Identity.Samples
For your purposes, my demo code is more relevant than the NuGet sample is, because it focuses just on token creation and validation. In particular, take a look at these two files:
Startup.Auth.cs.
We're instantiating the IDataProtectionProvider only once per application start.
public partial class Startup
{
public static IDataProtectionProvider DataProtectionProvider
{
get;
private set;
}
public void ConfigureAuth(IAppBuilder app)
{
DataProtectionProvider =
new DpapiDataProtectionProvider("WebApp2015");
// other code removed
}
}
AccountController.cs.
Then within the AccountController, we're using the static provider instead of creating a new one.
userManager.UserTokenProvider =
new DataProtectorTokenProvider<User>(
Startup.DataProtectionProvider.Create("UserToken"));
Just doing that might remove the bug you're seeing. Here are some questions for you to consider while troubleshooting further.
Are you using two different UserTokenProvider purposes?
The DataProtectorTokenProvider.Create(string[] purposes) method takes a purposes argument. Here is what MSDN has to say about that:
purposes. Additional entropy used to ensure protected data may only be unprotected for the correct purposes.
When you create the user code, you're using (at least) two different purposes:
user.Id
"ConfirmUser" and
the purpose of the ApplicationUserManager that you retrieve with GetOwinContext()....
Here's your code as a snippet.
userManager.UserTokenProvider =
new DataProtectorTokenProvider<User>(provider.Create(user.Id));
manager.UserTokenProvider =
new DataProtectorTokenProvider<User>(provider.Create("ConfirmUser"));
string code = Context
.GetOwinContext()
.GetUserManager<ApplicationUserManager ()
.GenerateEmailConfirmationToken(user.Id)
When you validate the code, you might be using the wrong purpose. Where do you assign the UserTokenProvider for the ApplicationUserManager that you use to confirm the email? It's purposes argument must be the same!
var manager = Context.GetOwinContext()
.GetUserManager<ApplicationUserManager>();
var result = manager.ConfirmEmail(userId, HttpUtility.UrlDecode(code));
There is a strong chance that the token is invalid because you're sometimes using a different UserTokenProvider purpose for creation than you're using for validation.
Why would this be sometimes? Do a thorough search of your code to find all the places that assign to UserTokenProvider. Maybe you override it somewhere unexpected (such as in a property or in the IdentityConfig.cs file) so that it seems random.
Has the TokenLifespan expired?
You've mentioned that the Invalid Token message occurs randomly. It might be that the token has expired. This tutorial notes that the default lifespan is one day. You can change it like this:
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>
(dataProtectionProvider.Create("WebApp2015"))
{
TokenLifespan = TimeSpan.FromHours(3000)
};
Why three UserManager instances?
Here are some comments on the code that creates the confirmation token. It seems that you're using a three separate UserManager instances including a derived ApplicationUserManager type. What's that about?
What is the type of manager here?
Why create a userManager instead of using the existing manager?
Why use manager.UserTokenProvider not userManager.UserTokenProvider?
Why are you getting a third UserManager instance from the Context?
Note that I have removed a lot of code to focus on just your token creation.
// 1.
IdentityResult result = manager.Create(user, "Password134567");
if (result.Succeeded)
{
var provider = new DpapiDataProtectionProvider("WebApp2015");
// 2.
UserManager<User> userManager =
new UserManager<User>(new UserStore<User>());
userManager.UserTokenProvider =
new DataProtectorTokenProvider<User>(provider.Create(user.Id));
// 3.
manager.UserTokenProvider =
new DataProtectorTokenProvider<User>(provider.Create("ConfirmUser"));
// 4.
string raw = Context.GetOwinContext()
.GetUserManager<ApplicationUserManager>()
.GenerateEmailConfirmationToken(user.Id)
// remaining code removed
}
I wonder whether we could simplify the above to use just one UserManager instance as follows.
// 1.
IdentityResult result = manager.Create(user, "Password134567");
if (result.Succeeded)
{
var provider = new DpapiDataProtectionProvider("WebApp2015");
manager.UserTokenProvider =
new DataProtectorTokenProvider<User>(provider.Create(user.Id));
// 3.
var provider = provider.Create("ConfirmUser");
manager.UserTokenProvider =
new DataProtectorTokenProvider<User>(provider);
// 4.
string raw = manager.GenerateEmailConfirmationToken(user.Id);
// remaining code removed
}
If you use this approach, be sure to use the same "ConfirmUser" purposes argument during confirmation of the email.
What's inside IdentityHelper?
Since the error is happening randomly, it occurs to me that the IdentityHelper methods might be doing something funky to the code that mucks up things. What's inside each of these methods?
IdentityHelper.GetUserConfirmationRedirectUrl()
IdentityHelper.RedirectToReturnUrl()
IdentityHelper.GetCodeFromRequest()
IdentityHelper.GetUserIdFromRequest()
I might write some tests to ensure that the raw code that your process creates always matches the raw code that your process retrieves from the Request. In pseudo-code:
var code01 = CreateCode();
var code02 = UrlEncode(code01);
var request = CreateTheRequest(code02);
var response = GetTheResponse();
var code03 = GetTheCode(response);
var code04 = UrlDecode(code03);
Assert.AreEquals(code01, code04);
Run the above 10,000 times to ensure that no problems exist.
Conclusion
It's my strong suspicion that the problem lies in using one purposes argument during token creation and another during confirmation. Use one purpose only and you might be fine.
Making this work on Azure Websites
Use SqlCompact instead of localdb.
Use app.GetDataProtectionProvider() not DpapiDataProtectionProvider because Dpapi does not work with web farms.
Is the site hosted on multiple web servers?
If so, you cannot use DPAPI here. It is machine-specific.
You'll need to use another data protection provider.
There might be some url-invalid characters in the code (token). Thus we need to use HttpUtility.UrlEncode(token) and HttpUtility.UrlDecode(token) when it appears in any url.
See something details here:
Identity password reset token is invalid
Whilst I think Shaun has provided great feedback to resolve such issues. There is one comment you made that makes me think it just might be an Alternate token issue. See also comments about multiple servers and Tokens.
... it's purely random
I dont think its random ;-). But what could make it work much of the time then for some users not.
A token was generated for a different page or APP, or is from the same APP and has just expired. Eg token valid for a short period. Is present in the browser. The token is from a similar app or from the same app on a different form/page.
The browser present the token since the token was generated for the Domain.
But when analyzed the token didnt match, or just expired.
Consider the lifecycle of the tokens.
I'm writing a web app that pulls events data from Facebook, and I can get a lot of the information using an app token, but not the picture, which requires a client token, as documented here: https://developers.facebook.com/docs/graph-api/reference/v2.2/event/picture
I want the code that grabs the event data to run automatically on a server at regular intervals, without requiring a user to log in to their Facebook account.
Is there a way I can get a client token without user intervention? If not, is there another way I can get the event picture?
This is the code I am using to get the event data, using C# and JSON.Net (This gets a list of events created by the specified user - ResortStudios):
var fb = new FacebookClient();
dynamic result = fb.Get( "oauth/access_token", new
{
client_id = "XXXXXXXXXXX",
client_secret = "XXXXXXXXXXXXXXXXXXXXXXXXX",
grant_type = "client_credentials"
} );
var apptoken = result.access_token;
fb = new FacebookClient(apptoken);
result = fb.Get("ResortStudios/events");
JObject events = JObject.Parse(result.ToString());
JArray aEvents = (JArray)events["data"];
string s = aEvents.ToString();
List<fbEvent> lEvents = JsonConvert.DeserializeObject<List<fbEvent>>(s);
I've not tried this but something occurred to me that might work for you. Have you considered something like storing it a non-persistent data store like session state? Then, using the Facebook SDK for .NET, you create an ActionResult for UserInfo, like below. (I know this isn't directly applicable but I hoped it might get you thinking.)
//http://facebooksdk.net/docs/web/ajax-requests/
public ActionResult UserInfo()
{
var accessToken = Session["AccessToken"].ToString();
var client = new FacebookClient(accessToken);
dynamic result = client.Get("me", new { fields = "name,id" });
return Json(new
{
id = result.id,
name = result.name,
});
}