object makes web method loop - c#

If I delete this value = new { token = 1 } or convert to value = "" webmethod works fine, otherwise method get triggered after return repeatedly.
Why this happens how to solve?
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "login/{username}/{password}")]
public Result Login(string username, string password)
{
somecode..
if (user != null && user.Password == password)
{
return new Result { statusCode = "200", message = "Success", value = new { token = 1 } };
}
else
{
return new Result { statusCode = "401", message = "Fail", value = "" };
}
}
public class Result
{
public string statusCode { get; set; }
public string message { get; set; }
public object value { get; set; }
}
this didn't work too;
return new Result { statusCode = "200", message = "Success", value = new Token { token = "some string" } }

Try Like This
public Result Login(string username, string password)
{
int token=1;
Result response = new Result();
if (user != null && user.Password == password)
{
response.message = "Success";
response.statusCode = "200";
response.value = token;
}
else
{
response.message = "Fail";
response.statusCode = "401";
response.value = null;
}
return response;
}
public class Result
{
public string statusCode { get; set; }
public string message { get; set; }
public object value { get; set; }
}

Related

ASP.NET Core Web API - How to register user and immediately login using a third party REST API

In my ASP.NET Core-6 Web API, I have an external API to consume. I am to validate the account using a parameter, register the user if not in existence, then Login with the same detail.
API:
https://api.thirdpartycompany.com/UserAccount/api/CustomerDetail?userName=
First, it checks if the customer exists in the external API using userName as parameter.
public class GetCustomerDetailDto
{
public class CustomerDetail
{
public string FirstName { get; set; }
public object LastName { get; set; }
public string UserName { get; set; }
public string EmailAddress { get; set; }
}
}
I validated the third party API using this method:
interface:
public interface IDataUtil
{
CustomerDetail GetCustomerDetail(string userName);
}
Implementation:
public class DataUtil : IDataUtil
{
private readonly IConfiguration _config;
private readonly ILogger<DataUtil> _logger;
private readonly HttpClient _myClient;
public DataUtil
(
IConfiguration config,
ILogger<DataUtil> logger,
HttpClient myClient
)
{
_config = config;
_logger = logger;
_myClient = myClient;
}
public CustomerDetail GetCustomerDetail(string userName)
{
var responseResults = new CustomerDetail();
_logger.LogError($"responseResults: " + responseResults);
try
{
string custAccountNoUrl = _config.GetSection("Endpoints").GetValue<string>("custAccountDetailUrl") + userName;
_myClient.DefaultRequestHeaders.Accept.Clear();
_myClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = _myClient.GetAsync(custAccountNoUrl).Result;
if (response.IsSuccessStatusCode)
{
var stringResult = response.Content.ReadAsStringAsync().Result;
responseResults = JsonConvert.DeserializeObject<CustomerDetail>(stringResult);
}
}
catch (Exception ex)
{
_logger.LogError($"An Error occured " + ex.ToString());
}
return responseResults;
}
}
I have these Auth DTOs:
public class UserDto
{
public string Id { get; set; }
public string FirstName { get; set; }
public string Lastname { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public DateTime LastLogin { get; set; }
}
public class LoginRequestDto
{
[Required(ErrorMessage = "The username is required!")]
public string UserName { get; set; }
[Required(ErrorMessage = "The password is required!")]
public string Password { get; set; }
}
public class LoginResponseDto
{
public string JwtToken { get; set; }
public UserDto User { get; set; }
public DateTime Expires { get; set; }
}
public class RegistrationRequestDto
{
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Model:
public class AppUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime LastLogin { get; set; }
}
And now the AuthService.
IAuthService:
public interface IAuthService
{
Task<GenericResponseDto<object>> LoginUser(LoginRequestDto request);
Task<GenericResponseDto<UserDto>> CreateUserAsync(RegistrationRequestDto requestDto);
}
AuthService:
private async Task<GenericResponseDto<UserDto>> CreateUserAsync(RegistrationRequestDto requestDto)
{
var response = new GenericResponseDto<UserDto>();
var existingUser = await _userManager.FindByNameAsync(requestDto.UserName);
if (existingUser == null)
{
var userDetail = _dataUtil.GetCustomerDetail(requestDto.UserName);
var user = new AppUser()
{
UserName = userDetail.UserName.ToLower().Trim(),
Email = userDetail.EmailAddress.Trim().ToLower(),
FirstName = userDetail.FirstName.Trim(),
LastName = userDetail.LastName.Trim(),
CreatedAt = DateTime.Now
};
user.SecurityStamp = Guid.NewGuid().ToString();
var result = await _userManager.CreateAsync(user, "Adminpass1");
if (!result.Succeeded)
{
var error = string.Join<IdentityError>(", ", result.Errors.ToArray());
response.Error = new ErrorResponseDto { ErrorCode = 500, Message = "Failed to create user because of the following errors: " + error };
}
else
{
response.StatusCode = 200;
response.Result = _mapper.Map<UserDto>(user);
}
} else
{
response.Error = new ErrorResponseDto { ErrorCode = 400, Message = "This email is already registered!" };
response.StatusCode = 400;
}
return response;
}
public async Task<GenericResponseDto<object>> LoginUser(LoginRequestDto request)
{
var user = await _userManager.FindByNameAsync(request.UserName);
var response = new GenericResponseDto<object>();
if (user != null && await _userManager.CheckPasswordAsync(user, request.Password))
{
var roles = await _userManager.GetRolesAsync(user);
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
foreach (var userRole in roles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
}
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var token = new JwtSecurityToken(
issuer: _configuration["JWT:ValidIssuer"],
audience: _configuration["JWT:ValidAudience"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
response.Result = new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
user = _mapper.Map<UserDto>(user),
expires = token.ValidTo
};
response.StatusCode = 200;
user.LastLogin = DateTime.Now;
try
{
await _context.SaveChangesAsync();
}catch(Exception ex)
{
response.Error = new ErrorResponseDto() { ErrorCode = 500, Message = ex.Message };
}
return response;
}
response.StatusCode = 400;
response.Error = new ErrorResponseDto { ErrorCode = 400, Message = "Invalid email or password!" };
return response;
}
In the application, users are not allowed to register manually.
So far, I have created the LoginUser and CreateUserAsync methods.
What I want to achieve is that, when the user tries to login the application checks if username already exists. If yes, it logs in, if no it checks from the external API using UserName as parameter, gets the user data, register the user using CreateUserAsync. Then automatically re-login the user.
How do I achieve this?
NOTE: I am using IdentityDB and EntityFramework
Thanks

How to Update Employee and Identity User with one to one/zero relation

I am trying to update employee record and want to update identity user too.
If i update Identity User first separately
For Example:
UserManager.Update(user);
Context.Entry(employee).State = System.Data.Entity.EntityState.Modified;
Context.SaveChanges();
and then update the employee.
maybe it is possible identity user updates with success but employee update process gets an error.
so IdentityUser is updated now but the employee is not.
how to handle this situation.
please guide.
public class Employee
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string AppUserId { get; set; }
[ForeignKey("AppUserId")]
public virtual AppUser AppUser { get; set; }
}
public class AppUser : IdentityUser<string, AppUserLogin, AppUserRole, AppUserClaim>, IUser<string>
{
public AppUser()
{
this.Id = Guid.NewGuid().ToString();
}
public async Task<ClaimsIdentity>
GenerateUserIdentityAsync(UserManager<AppUser, string> manager)
{
var userIdentity = await manager
.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
[Required]
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsActive { get; set; }
}
public JsonResult Create(EmployeeVM evm, AppUserVM appUser)
{
var jsonResult = new JsonResult();
jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
if (ModelState.IsValid)
{
var user = new AppUser();
evm.CreatedDate = DateTime.Now.Date;
appUser.PasswordHash = "dummypass";
user = Mapper.Map<AppUser>(appUser);
var employee = Mapper.Map<Employee>(evm);
employee.AppUser = user;
try
{
if (userService.CreateEmployee(employee))
{
jsonResult.Data = new { Success = true, message = "Success Added Record"};
}
}
catch (Exception ex)
{
jsonResult.Data = new { Success = false, message =ex.Message};
}
}
else
{
jsonResult.Data = new { Success = false, message = ModelErrors() };
}
return jsonResult;
}
public bool CreateEmployee(Employee employee)
{
Context.Employees.Add(employee);
return Context.SaveChanges()>0;
}
Adding new record works fine.
but when i update the record. i don't know how to update both records at once.
For Example:
public JsonResult Edit(EmployeeVM evm, AppUserVM appUserVM)
{
ModelState.Remove(nameof(evm.CreatedDate));
var jsonResult = new JsonResult();
jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
if (ModelState.IsValid)
{
appUserVM.UserName = appUserVM.Email;
var user = UserManager.FindById(evm.UserId);
user.Email = appUserVM.Email;
user.UserName = appUserVM.UserName;
user.FirstName = appUserVM.FirstName;
user.LastName = appUserVM.LastName;
user.IsActive = appUserVM.IsActive;
user.PhoneNumber = appUserVM.PhoneNumber;
var employee = Mapper.Map<Employee>(evm);
employee.AppUser = user;
employee.Id = evm.Id;
employee.AppUserId = user.Id;
try
{
if(userService.UpdateEmployee(employee))
jsonResult.Data = new { Success = true, message = "Success" };
}
catch (Exception ex)
{
jsonResult.Data = new { Success = false, message = ex.Message };
}
}
else
{
jsonResult.Data = new { Success = false, message = ModelErrors() };
}
return jsonResult;
}
public bool UpdateEmployee(Employee employee)
{
Context.Entry(employee).State = System.Data.Entity.EntityState.Modified;
return Context.SaveChanges() > 0;
}
Without seeing the exception, I'm not sure what the issue is, but you could trying using an attached entity and set values like the following.
var dbEmployee = Context.Emplyoees.SingleOrDefault(s => s.Id == employee.Id);
if (dbEmployee!= null)
Context.Entry(dbEmployee).CurrentValues.SetValues(employee);
The User employee service should be
public bool UpdateEmployee(Employee employee)
{
var existingEmployee = Context.Emplyoees.FirstOrDefault(s => s.Id == employee.Id);
if (existingEmployee != null)
{
//do the update to the database
Context.Entry(existingEmployee).CurrentValues.SetValues(employee);
Context.Entry(existingEmployee).State = System.Data.Entity.EntityState.Modified;
return Context.SaveChanges() > 0;
}
else return false;
}

How to read the contents of a json post with asp before processing the request?

What I want to do is extremely simple in php. I just want to read the contents of the post. It also extremely simple on sailsjs / node ... I just return the result from within the async function.
In c# asp the answer is eluding me. I want the function to read the contents of the post before it attempts to process the post.
Sometimes the following code works. Sometimes the reading of the json from the post happens too slowly and jsonText is read as "" so nothing is processed.
In all of the test runs the json is being sent in the body of the post.
What is the best way to return a httpResponse after making sure the contents of the post is read first?
public HttpResponseMessage Post()
{
string content;
try
{
string result = String.Empty;
Newtonsoft.Json.Linq.JObject jObject = null;
string jsonText = String.Empty;
var syncTask = new Task<string>( () => {
return Request.Content.ReadAsStringAsync().Result;
});
/* I'm expecting that this will finish */
syncTask.RunSynchronously();
jsonText = syncTask.Result;
/* before this line of code executes */
System.Net.Http.HttpResponseMessage response = new HttpResponseMessage();
if (jsonText == "")
{
result = "{\"error\":\"body is empty\"}";
response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
}
else
{
jObject = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.Linq.JRaw.Parse(jsonText);
string ipAddress = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
jObject["ipAddress"] = ipAddress;
Models.JsonXML jsonXml = new JsonXML(jObject.ToString(Newtonsoft.Json.Formatting.None));
System.Xml.XmlDocument document = new System.Xml.XmlDocument();
document.LoadXml(jsonXml.xml);
result = ReferralsManager.ProcessReferral(document);
if (result == "")
{
result = "{}";
}
response.StatusCode = System.Net.HttpStatusCode.OK;
}
response.Content = new StringContent(result);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
return response;
}
catch (Exception ex)
{
content = ErrorMessage.ServerException(Converter, ex);
return Request.ToResponseMessage(content);
}
finally
{
LogManager.GetCurrentClassLogger().Info(InfoMessage.FUNC_ENDS, "Process Referral");
}
}
The working modified code after the answer from #Mekap is
public class ProcessReferralAddressModel {
public ProcessReferralAddressModel() { }
public string address { get; set; }
public string name { get; set; }
}
public class ProcessReferralModel
{
public ProcessReferralModel()
{
}
public string uuid { get; set; }
public DateTime date { get; set; }
public ProcessReferralAddressModel from { get; set; }
public ProcessReferralAddressModel[] to { get; set; }
public string subject { get; set; }
public string text { get; set; }
public string html { get; set; }
}
/// <summary>
/// Process a referral.
/// </summary>
/// <param name="userid">The userid.</param>
/// <returns></returns>
public HttpResponseMessage Post([FromBody] ProcessReferralModel processReferralModel)
{
string content;
string jsonText = Newtonsoft.Json.JsonConvert.SerializeObject(processReferralModel) ;
try
{
string result = String.Empty;
Newtonsoft.Json.Linq.JObject jObject = null;
System.Net.Http.HttpResponseMessage response = new HttpResponseMessage();
if (jsonText == "" || jsonText == null )
{
result = "{\"error\":\"body is empty\"}";
response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
}
else
{
jObject = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.Linq.JRaw.Parse(jsonText);
string ipAddress = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
jObject["ipAddress"] = ipAddress;
Models.JsonXML jsonXml = new JsonXML(jObject.ToString(Newtonsoft.Json.Formatting.None));
System.Xml.XmlDocument document = new System.Xml.XmlDocument();
document.LoadXml(jsonXml.xml);
result = ReferralsManager.ProcessReferral(document);
if (result == "")
{
result = "{}";
}
response.StatusCode = System.Net.HttpStatusCode.OK;
}
response.Content = new StringContent(result);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
return response;
}
catch (Exception ex)
{
content = ErrorMessage.ServerException(Converter, ex);
return Request.ToResponseMessage(content);
}
finally
{
LogManager.GetCurrentClassLogger().Info(InfoMessage.FUNC_ENDS, "Process Referral");
}
}
The json you're fetching, for our example will look something like
{ "ID" : 3,
"StringCmd" : "ls -l"
}
For starters, we are going to write a small class who's representing our data in your web api
public class StringCmdModel
{
public StringCmdModel()
{
}
public int ID { get; set; }
public string StringCmd { get; set; }
}
Now, we just have to write our Entry point in our WebAPI :
[HttpPost]
public HttpResponseMessage PostFonction([FromBody] StringCmdModel NewEntry)
You don't have to check for the existence of the data inside the function. But you should still do proper checks on theirs values, in case you get bad formated json or malicious calls.
But, if you get a call with json that is not matching the StringCmdModel you gave in parameter from the body, this function will not be executed, and the server will throw on its own a 500 error.

Client.ExecuteAsync loses variable data before saving to database

I have below code to send email to multiple email ids and am using RestSharp request and response with MailGun API
var emodel = model as EmailViewModel;
var context = HttpContext.Current;
var from = "KG <" + emodel.FromEmail[0] + ">";
var client = new RestClient
{
BaseUrl = new Uri("https://api.mailgun.net/v3"),
Authenticator = new HttpBasicAuthenticator("api", WebConfigurationManager.AppSettings["MGKey"])
};
foreach(var to in emodel.EmailID)
{
var request = new RestRequest();
request.AddParameter("domain",
"domain.com", ParameterType.UrlSegment);
request.Resource = "{domain}/messages";
request.AddParameter("from", from);
request.AddParameter("subject", emodel.Subject ? ? "No Subject");
var body = emodel.Message ? ? "Empty Message";
request.AddParameter("html", body);
request.Method = Method.POST;
request.AddParameter("to", to);
var json = new JavaScriptSerializer();
client.ExecuteAsync(request, r => {
var content = json.Deserialize<Dictionary<string,string >>(r.Content);
if (content != null && r.ResponseStatus == ResponseStatus.Completed && r.StatusCode == HttpStatusCode.OK)
{
msgId=content.msgID;
}
if (msgId != "")
{
using(_db = new DBcontext())
{
var message = new tblMsg {
MDSent = DateTime.Today.Date,
MMsg = WebUtility.HtmlEncode(emodel.Message),
MMsgStatus = EventTypes.Stored.ToString(),
MMsgType = true,
MSByID = from,
MSByUser = loggedInUser,
MSID = msgId,
MSub = emodel.Subject ? ? "No subject",
MToID = to
};
_db.Entry(message).State = EntityState.Added;
_db.SaveChanges();
}
}
else {
LogError.LogMessage(r.ErrorMessage, context);
}
});
}
EmailViewModel.cs
public class EmailViewModel
{
public string[] EmailID { get; set; }
public SelectList Emails { get; set; }
public string[] Names { get; set; }
public string Message { get; set; }
public string[] FromEmail { get; set; }
public SelectList FromEmails { get; set; }
public bool HasAttachment { get; set; }
public string AttachmentPath { get; set; }
public int AttachmentCount { get; set; }
public string Subject { get; set; }
}
The problem over here is when I send an email to multiple ids, because of client.ExecuteAsync line which is inside for-loop, it will fetch async response multiple times and store it in content and before message record saves into database, it gets replaced with the next async response from API and hence only one record gets saved in database. Is there any mechanism in C#, wherein I can hold variable message value until its saved to database? I tried using lock on content variable, but it did not help.. Hoping to find some help.

Call Salesforce API to Add Leads using ASP.net

I am trying to call Salesforce Parnter wsdl to Create Leads to their system through my c# code.
but its giving me error:
Cannot implicitly convert type Contact[]' to 'sforce.sObject'
private string userID = "sasxxasasas#saasforce.in";
private string password = "sadwdasdasdasdsadasdsxzdddw";
private DateTime _nextLoginTime;
private string _sessionId;
string url="valueleads.in/pushleads/websvc/cigna/wsdl.xml";
SforceService binding;
private void getSessionInfo()
{
sforce.SforceService partnerService = new sforce.SforceService();
sforce.LoginResult lr = new sforce.LoginResult();
lr = partnerService.login(userID, password);
_sessionId = lr.sessionId;
Session["_sessionId"] = lr.sessionId;
Session["_serverUrl"] = lr.serverUrl;
Session["_nextLoginTime"] = DateTime.Now;
binding.SessionHeaderValue = new sforce.SessionHeader();
binding.SessionHeaderValue.sessionId = _sessionId;
binding.Url = lr.serverUrl;
}
public bool IsConnected()
{
bool blnResult = false;
if (!string.IsNullOrEmpty(_sessionId) & _sessionId != null)
{
if (DateTime.Now > _nextLoginTime)
blnResult = false;
else
blnResult = true;
}
else
blnResult = false;
return blnResult;
}
public void create()
{
if (!IsConnected())
{
getSessionInfo();
}
binding = new SforceService();
Contact contact=new Contact();
contact.fname="Eric";
contact.lname="Peter";
contact.mobile="9898989889";
Contact[] contacts = { contact };
string result;
sforce.SaveResult[] createResults = binding.create(new sObject[] { contacts });
if (createResults[0].success)
{
result = createResults[0].id;
}
else
{
result = createResults[0].errors[0].message;
}
Response.Write(result);
}
}
public class Contact
{
public String fname { get; set; }
public String lname { get; set; }
public String mobile { get; set; }
}
}
please help, very much new to this salesforce API.
You need to create an array of SObjects, not contacts, so do
sforce.sObject[] contacts = { contact };
string result;
sforce.SaveResult[] createResults = binding.create(contacts);

Categories