How to receive posted values to variable in .asmx that was posted from extjs, so it can be saved using ado.net to database?
SENDING DATA WITH EXT.AJAX
{
text: 'Add',
formBind: true,
disabled: true,
handler: function () {
var form = this.up('form').getForm();
var formValues = form.getValues();
var firstName = formValues.firstName;
var lastName = formValues.lastName;
if (form.isValid()) {
Ext.Ajax.request({
url: 'WebServices/WebService.asmx/AddAgent',
headers: { 'Content-Type': 'application/json' },
method: 'POST',
jsonData: { FirstName: firstName, LastName: lastName }
});
}
}
}
When submited, firebug reports error:
How to properly recieve this values in .asmx so they can be used in [WebMethod] and saved with Ado.Net?
[Serializable]
public class Agents
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
//CREATE
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public string AddAgent()
{
string connStr = ConfigurationManager.ConnectionStrings["AgentsServices"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connStr))
{
connection.Open();
using (SqlCommand command = new SqlCommand("insert into Agent(id, firstName, lastName) values(#id, #firstName, #lastName)", connection))
{
command.Parameters.AddWithValue("#firstName", FirstName); //here i get message( The name "FirstNAme does not exist in current context")
command.Parameters.AddWithValue("#lastName", LastName); // -||-
command.ExecuteNonQuery();
}
}
}
EDIT:
No. stil 500 Internal Server Error:
Your web method doesn't seem to take any argument. Also your method expects to return a string and yet you do not return anything. So either return something or modify your method signature to void. Also you have set UseHttpGet = true and yet you are sending a POST request. Try like this:
[WebMethod]
[ScriptMethod]
public void AddAgent(Agents agents)
{
string connStr = ConfigurationManager.ConnectionStrings["AgentsServices"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connStr))
{
connection.Open();
using (SqlCommand command = new SqlCommand("insert into Agent(id, firstName, lastName) values(#id, #firstName, #lastName)", connection))
{
command.Parameters.AddWithValue("#firstName", agents.FirstName);
command.Parameters.AddWithValue("#lastName", agents.LastName);
command.ExecuteNonQuery();
}
}
}
Also since you have defined the Id property of your Agents model as a non-nullable integer I would recommend you sending a value for it:
jsonData: { agents: { Id: 0, FirstName: firstName, LastName: lastName } }
Related
I am trying to implement on a Blazor-Server side application a simple login against LDAP server and use cookie to store user claims. I have the MainLayout set to Authorized, if the user is not authenticated it will be re-direct to Login page. I have already tested the LDAP connection and it works properly, the problem is no matter what I do the cookie doesn't get created in the browser. When I run the POST command I see the HttpStatusCode.OK but the cookie it's not created and the browser re-direct again to login page of course.
Can someone please tell me what am I doing wrong? My code:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
AuthenticationController.cs
[ApiController]
public class AuthenticationController : Controller
{
[HttpPost]
[Route("authentication/login")]
public async Task<ActionResult> Login([FromBody]UserCredentials credentials)
{
string path = "LDAP://serveraddress.xxx";
try
{
using DirectoryEntry entry = new(path, credentials.Username, credentials.Password);
using DirectorySearcher searcher = new(entry);
searcher.Filter = $"(&(objectclass=user)(objectcategory=person)(samaccountname={credentials.Username}))";
var result = searcher.FindOne();
if (result != null)
{
List<Claim> claims = new();
claims.Add(new Claim(ClaimTypes.Name, credentials.Username));
//Get Groups
ResultPropertyCollection fields = result.Properties;
foreach (var group in result.Properties["memberof"])
{
var distinguishedName = new X500DistinguishedName(group.ToString());
var commonNameData = new AsnEncodedData("CN", distinguishedName.RawData);
var commonName = commonNameData.Format(false);
if (!string.IsNullOrEmpty(commonName))
{
claims.Add(new Claim(ClaimTypes.Role, commonName));
}
}
//Get Emails
foreach (var email in result.Properties["mail"])
{
claims.Add(new Claim(ClaimTypes.Email, email.ToString()));
}
ClaimsIdentity claimsIdentity = new(claims, CookieAuthenticationDefaults.AuthenticationScheme);
AuthenticationProperties authProperties = new()
{
AllowRefresh = true,
IssuedUtc = DateTime.Now,
ExpiresUtc = DateTimeOffset.Now.AddDays(1),
IsPersistent = true,
};
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);
return Ok();
}
else
{
return NotFound("User Not Found!");
}
}
catch (Exception)
{
return NotFound("Login credentials is incorrect!");
}
}
[HttpPost]
[Route("authentication/logout")]
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Ok();
}
}
Login.razor
#page "/login"
#page "/login/{ErrorMessage}"
#layout CenteredBlockLayout
#attribute [AllowAnonymous]
<MudPaper Elevation="25" Class="pa-8" Width="100%" MaxWidth="500px">
<MudItem><img src="/images/logo.svg" alt="Logo" style="width:400px; height:50px;" /></MudItem>
<MudText Typo="Typo.h4" GutterBottom="true">Sign In</MudText>
<MudTextField #bind-Value="#Username" T="string" Label="Username"/>
<MudTextField #bind-Value="#Password" T="string" Label="Password"/>
<MudButton OnClick="(() => PerformLoginAsync())">Sign In</MudButton>
</MudPaper>
#if (!string.IsNullOrEmpty(ErrorMessage))
{
<MudAlert Severity="Severity.Error">#ErrorMessage</MudAlert>
}
Login.razor.cs
public partial class Login
{
public string Username { get; set; }
public string Password { get; set; }
[Parameter]
public string ErrorMessage { get; set; }
[Inject]
HttpClient Client { get; set; }
[Inject]
private NavigationManager NavMan { get; set; }
private async Task PerformLoginAsync()
{
if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password))
{
UserCredentials cred = new UserCredentials
{
Username = Username,
Password = Password
};
var serialized = JsonConvert.SerializeObject(cred);
var stringContent = new StringContent(serialized, Encoding.UTF8, "application/json");
using var result = await Client.PostAsync($"NavMan.BaseUri}authentication/login", stringContent);
if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
NavMan.NavigateTo("/", true);
}
else
{
ErrorMessage = await result.Content.ReadAsStringAsync();
}
}
}
}
I believe you need to append the cookie to the response. I haven't tested this with your code but it should work something like this:
HttpContext.Response.Cookies.Append("my_cookie", claimsString, new CookieOptions()
{
Domain = "mydomain.com",
SameSite = SameSiteMode.Lax,
Secure = true,
Path = "/",
Expires = DateTime.UtcNow.AddDays(1)
}
(These cookie options are just an example, of course. Tailor them to your specific needs.)
Keep in mind that you'll need to convert your claims to a string so that you can store it as the value in a cookie. In our case we store claims in a JWT, so that's what gets stored in the cookie. Here's how I do it:
public string CreateJWT(HttpContext httpContext, User user)
{
var handler = new JwtSecurityTokenHandler();
var descriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[] {
new Claim(ClaimTypes.GivenName, user.FirstName),
new Claim(ClaimTypes.Surname, user.LastName),
new Claim(ClaimTypes.Name, $"{user.FirstName} {user.LastName}"),
new Claim(ClaimTypes.Email, user.Email),
}),
Expires = DateTime.UtcNow.AddMinutes(Config.AccessExpMins),
Issuer = Config.Issuer,
Audience = Config.Audience,
SigningCredentials = new SigningCredentials(Key, SecurityAlgorithms.RsaSha256)
};
var token = handler.CreateJwtSecurityToken(descriptor);
var accessToken = handler.WriteToken(token);
httpContext.Response.Cookies.Append("my_cookie", accessToken, new CookieOptions()
{
Domain = Config.CookieDomain,
SameSite = SameSiteMode.Lax,
Secure = true,
Path = "/",
Expires = DateTime.UtcNow.AddMinutes(Config.AccessExpMins)
});
return accessToken;
}
As for parsing the JWT, I'm sure there are a number of ways to go about it. The one that worked for me was this one.
I created a DynamoDb using NET and able to getitem, which is not an empty list. I get a status 400 error on the putitem using Postman. This is the error:
"errors": {
"id": [
"Could not convert string to integer: 9134d3a0-a6bf-4409-87b3-d9fad02bd31c. Path 'id', line 2, position 44."
]
},
This is the body I use for the post:
{
"id":"9134d3a0-a6bf-4409-87b3-d9fad02bd31c",
"replyDateTime": "63669789320007900",
"body":"a good body",
"title":"best title",
"creator": " James"
}
This is my createtable code:
var request = new CreateTableRequest
{
AttributeDefinitions = new List<AttributeDefinition>
{
new AttributeDefinition
{
AttributeName = "Id",
AttributeType = "S"
},
new AttributeDefinition
{
AttributeName = "ReplyDateTime",
AttributeType = "S"
}
},
KeySchema = new List<KeySchemaElement>
{
new KeySchemaElement
{
AttributeName = "Id",
KeyType = "HASH" // Partition Key
},
new KeySchemaElement
{
AttributeName = "ReplyDateTime",
KeyType = "Range" // Sort Key
}
},
this is the putitem code:
public async Task AddNewEntry(string id, string replyDateTime, string body, string title, string creator)
{
var queryRequest = RequestBuilder(id, replyDateTime, body, title, creator);
await PutItemAsync(queryRequest);
}
private PutItemRequest RequestBuilder(string id, string replyDateTime, string body, string title, string creator)
{
var item = new Dictionary<string, AttributeValue>
{
{"Id", new AttributeValue {S = id}},
{"ReplyDateTime", new AttributeValue {S = replyDateTime}},
{"Body", new AttributeValue {S = body}},
{"Creator", new AttributeValue {S = creator}},
{"Title", new AttributeValue {S = title}}
};
return new PutItemRequest
{
TableName = "BlogDynamoDbTable",
Item = item
};
}
private async Task PutItemAsync(PutItemRequest request)
{
await _dynamoClient.PutItemAsync(request);
}
}
I believe I made the primary key a string. Why is an integer even mentioned in the error message?
I found my error. The model file was defining id as an integer. Grrr
I changed it to string and it posts.
public class Item
{
[Amazon.DynamoDBv2.DataModel.DynamoDBHashKey]
public string Id { get; set; }
[Amazon.DynamoDBv2.DataModel.DynamoDBRangeKey]
public string ReplyDateTime { get; set; }
public string Body { get; set; }
public string Title { get; set; }
public string Creator { get; set; }
}
I think this is because my json gives me an array, but I don't know how it solved, this is what I did. (I'm new at this)
running in Visual Studio 2019 (xamarin.form) with web services but the url is hidden for security, so don't pay attention in that.
---my-json---
{
"cuentas":[
{
"cuenta":"0500",
"usuario":41
},
{
"cuenta":"0508",
"usuario":6
},
{
"cuenta":"0522",
"usuario":41
},
{
"cuenta":"0532",
"usuario":41
},
null
]
}
---WSClient.cs---
class WSClient
{
public async Task<T> Post<T>(string url, StringContent c)
{
var client = new HttpClient();
var response = await client.PostAsync(url, c);
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(json);
}
}
----Cuenta.cs---
public class Cuenta
{
public string cuenta { get; set; }
public int usuario { get; set; }
}
------MainPage.xaml.cs-----
private async void BtnCall_Clicked(object sender, EventArgs e)
{
WSClient client = new WSClient();
string dato = "";
StringContent content = new StringContent(dato, Encoding.UTF8, "application/json");
var result = await client.Post<Cuenta>("http://www.***", content);
if (result != null) {
lblCuenta.Text = result.cuenta;
lblUsuario.Text = result.cuenta;
}
}
It doesn't show me anything and it doesn't give me any mistakes... any advice?
( I can see the json in the console if I use WriteLine in "WSClient" )
your class should look like this (using json2csharp.com)
public class Cuenta
{
public string cuenta { get; set; }
public int usuario { get; set; }
}
public class RootObject
{
public List<Cuenta> cuentas { get; set; }
}
var result = await client.Post<RootObject>("http://www.***", content);
I have an app that allows users to log in via facebook, once user enters their credentials - My api request saves the user onto the database and auto-generates a user token(This is unique to each user). In order to display user specific details once user logs in - the token needs to be referenced. I am trying to get this token to the PCL project but it returns null just for the token. When I tried passing another string like name, it passes the correct value. Any help will be much appreciated.Thanks
FacebookRender in droid:
public class FacebookRender : PageRenderer
{
public FacebookRender()
{
CustomerService customerService = new CustomerService();
String error;
var activity = this.Context as Activity;
var auth = new OAuth2Authenticator(
clientId: "",
scope: "",
authorizeUrl: new Uri("https://www.facebook.com/dialog/oauth/"),
redirectUrl: new Uri("https://www.facebook.com/connect/login_success.html")
);
auth.Completed += async (sender, eventArgs) =>
{
try
{
if (eventArgs.IsAuthenticated)
{
await AccountStore.Create().SaveAsync(eventArgs.Account, "FacebookProviderKey");
var accessToken = eventArgs.Account.Properties["access_token"].ToString();
var expiresIn = Convert.ToDouble(eventArgs.Account.Properties["expires_in"]);
var expiryDate = DateTime.Now + TimeSpan.FromSeconds(expiresIn);
var request = new OAuth2Request("GET", new Uri("https://graph.facebook.com/me?fields=email,first_name,last_name,gender,picture"), null, eventArgs.Account);
var response = await request.GetResponseAsync();
var obj = JObject.Parse(response.GetResponseText());
var id = obj["id"].ToString().Replace("\"", "");
var name = obj["first_name"].ToString().Replace("\"", "");
var surname = obj["last_name"].ToString().Replace("\"", "");
var gender = obj["gender"].ToString().Replace("\"", "");
//var email = obj["email"].ToString().Replace("\"", "");
Customer.Customers cust = new Customer.Customers();
cust.Credentials = new Customer.Credentials();
cust.Name = name;
cust.Surname = surname;
cust.Email = "";
cust.MobilePhone = "";
cust.DOB = DateTime.Now;
cust.Number = "";
cust.City = "";
cust.Region = "";
cust.Country = "";
cust.DeviceToken = "sample";
cust.Credentials.SecretKey = "";
await customerService.AddCustomer(cust);
App.SaveToken(cust.Credentials.Token); - **//This is where I am passing the token**
App.NavigateToProfile(string.Format(name + surname));
}
else
{
App.NavigateToProfile("Invalid Login");
}
}
catch(Exception ex)
{
error = ex.Message;
}
};
activity.StartActivity(auth.GetUI(activity));
}
App.cs
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
public static void NavigateToProfile(string message)
{
App.Current.MainPage = (new Profile(message));
}
static string _Token;
public static string Token
{
get { return _Token; }
}
public static void SaveToken(string token)
{
_Token = token;
}
AboutPage.cs - I am passing the token in a label just to see if it's passing
public partial class About : ContentPage
{
private Label _lbltoken;
public About()
{
//InitializeComponent();
Appearing += (object s, EventArgs a) => {
_lbltoken.Text = App.Token;
};
string tk = App.Token;
_lbltoken = new Label()
{
FontSize = 20,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Text = tk,
};
var stack = new StackLayout
{
VerticalOptions = LayoutOptions.StartAndExpand,
Children = { _lbltoken },
};
Content = stack;
}
}
You can use the MessagingCenter.
Messages may be sent as a result like a button click, a system event or some other incident. Subscribers might be listening in order to change the appearance of the user interface, save data or trigger some other operation.
More Info
I don't really now if its good idea use static fields in App class. Xamarin access all fields with service locator, App.Current.[property] I will suggest you try to change these fields to public
string _Token;
public string Token
{
get { return _Token; }
}
public void SaveToken(string token)
{
_Token = token;
}
and use it with App.Current.SaveToken(token) or App.Current.Token
Angular newbie and I have had no luck getting to the bottom of this one. I am trying to send an update call to my RESTful web service. I am passing and int and an object. When debugging back at the web service, the int comes in fine, however the object always come is as NULL. Debugging before the call is made shows that the object has a value. Why am I getting NULL for my object in the web service?
I have tried making the call from a factory as well as the save function. Both are null when the web service is called.
app.js
TournamentDirectorApp.factory('tournamentFactory', function () {
return {
addUserToTournament: function (id, tourney, user, Tournament) {
tourney.Users.push(user)
var response = Tournament.update({ id: id }, { tourney: tourney })
return tourney;
}
};
});
$scope.save = function () {
var updatedTournament = tournamentFactory.addUserToTournament(id, selectedTourney, $scope.selectedUser, Tournament);
Tournament.update({ id: id }, { tournament: updatedTournament }, function () {
$location.path('/')
});
};
web service
public HttpResponseMessage PutTournament(int id, Tournament tournament)
{
if (ModelState.IsValid && id == tournament.TournamentId)
{
db.Entry(tournament).State = EntityState.Modified;
db.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
* tournament object *
public class Tournament
{
public int TournamentId { get; set; }
public string Director { get; set; }
public string Description { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public virtual List<Classification> Classifications { get; set; }
public virtual List<User> Users { get; set; }
}
* app.js (routing for the update) *
TournamentDirectorApp.factory('Tournament', function ($resource) {
return $resource('/api/tournament/:id', { id: '#id' }, {update: { method: 'PUT' }});
});
Based on the "update" example in the angular docs, I think the problem is that you should just send just the updatedTournament with the update request, not an object wrapping your changed object. Try:
Tournament.update({ id: id }, updatedTournament, function () {
$location.path('/') })
in your save function.