Integrating ASP.NET Web Api and Android Volley - web-services

I'm developing an ASP.NET Web Api project with Entity Framework and other project with Android and the Volley lib.
The idea is the project in ASP.NET to be the server and the Android app the client.
Both projects already work. The ASP.NET project is already connected to SQL Server and returns values in json format from one database, and the client also parses json from an online server that I used for testing when I was following one tutorial.
ASP.NET Web Api Controller:
public class StoreController : ApiController
{
// GET: api/Store
public IEnumerable<bo> Get()
{
using (EGLA_PHCEntities services = new EGLA_PHCEntities())
{
return services.bo.Where(e => e.nmdos == "Ficha Servico 30").Where(e => e.fechada == false).ToList();
}
}
...
}
Android:
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray(null);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject employee = jsonArray.getJSONObject(i);
String firstName = employee.getString("fieldA");
String mail = employee.getString("fieldB");
mTextViewResult.append(firstName + ", " + mail + "\n\n");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
The problem is that my project in ASP.NET does not return a name for the array of objects, and Android is waiting for a name.
The solution can be applied in one side or another. It can go through the ASP.NET project to return a name, or the project in Android to parse the json with an empty array name.
Modified because the list of fields is very extense:
[
{
"fieldA":"Something",
"fieldB":"Store 30",
},
{
"fieldA":"Something 2",
"fieldB":"Store 30 2",
}
]
The error that is returned in the Android app is "org.json.JSONException: No value for null". If I change
JSONArray jsonArray = response.getJSONArray(null);
to:
JSONArray jsonArray = response.getJSONArray("services");
The error returned is: "org.json.JSONException: No value for services"

Related

SharePoint Office365 Signin issue using CSOM

I am trying to connect and retrieve a List from my Office365 sharepoint portal through CSOM. In document.ready function of jquery I am calling an ajax call.
I am using the below code and its working fine.
[WebMethod]
public static List<myClass> GetDataOnPageLoad()
{
List<myClass> objmyClass = new List<myClass>();
string strSiteCollection = "<Site Url>";
string login = "<username>";
string password = "<password>";
SecureString securePassword = new SecureString();
foreach (char c in password)
securePassword.AppendChar(c);
try
{
ClientContext Clientcontext = new ClientContext(strSiteCollection);
Clientcontext.Credentials = new SharePointOnlineCredentials(login, securePassword);
DataTable dtData = new DataTable();
dtData.Columns.Add("ID", typeof(string));
dtData.Columns.Add("UserEmail", typeof(string));
dtData.Columns.Add("InstalledVersion", typeof(string));
if (Clientcontext != null)
{
List docList = Clientcontext.Web.Lists.GetByTitle("<List Name>");
Microsoft.SharePoint.Client.ListItemCollection items = docList.GetItems(CamlQuery.CreateAllItemsQuery());
Clientcontext.Load(items);
Clientcontext.ExecuteQuery();
foreach (var item in items)
dtData.Rows.Add(item["ID"].ToString(), item["UserEmail"].ToString(), item["InstalledVersion"].ToString());
}
if (dtData != null && dtData.Rows.Count > 0)
{
for (int i = 0; i < dtData.Rows.Count; i++)
{
//binding list
}
}
}
catch (Exception ex)
{
}
return objmyClass;
}
All good till now.
Now I in another project I need this same code.
So I copied it and pasted in the new project. Included the sharepoint client dll. Calling this from ajax. Now when I am running this new project it gives an exception from Clientcontext.ExecuteQuery();
Exception says : The partner returned a bad sign-in name or password error. For more information, see Federation Error-handling Scenarios.
I searched for this error but it didn't helped. I'm running the two projects side by side. The old one is running perfectly but the new one is getting the above said error.
Please help. Thanks & Regards.

Angular2 ASP.NET Core AntiForgeryToken

I have an Angular2 app. It is running within ASP.NET 5 (Core).
It makes Http calls to the controller which is working fine.
But now I need to establish Cross Site Scripting projection.
How do I generate a new token on each Http request and then subsequently perform the AntiForgeryToken check in Angular2 apps?
Note: My data forms in Angular are not produced from an MVC view but entirely written in Angular2 and call web services only.
All the examples I have seen are out dated and do not work / do not work fully.
How do I integrate AntiForgeryToken checks in Angular2 against ASP.NET 5 where forms are pure Angular?
Thanks.
A custom action filter is not necessary. It can all be wired up in Startup.cs.
using Microsoft.AspNetCore.Antiforgery;
(...)
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
(...)
}
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.Use(next => context =>
{
if (context.Request.Path == "/")
{
//send the request token as a JavaScript-readable cookie, and Angular will use it by default
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });
}
return next(context);
});
(...)
}
Then all you need in your controllers is the [ValidateAntiForgeryToken] decorator wherever you want to enforce that a token is provided.
For reference, I found this solution here - AspNet AntiForgery Github Issue 29.
I am using a action filter to send the request tokens.
Simply apply it to the actions you want a new antiforgery token, e.g. Angular2 SPA, WebAPI action, etc.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class AngularAntiForgeryTokenAttribute : ActionFilterAttribute
{
private const string CookieName = "XSRF-TOKEN";
private readonly IAntiforgery antiforgery;
public AngularAntiForgeryTokenAttribute(IAntiforgery antiforgery)
{
this.antiforgery = antiforgery;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
base.OnResultExecuting(context);
if (!context.Cancel)
{
var tokens = antiforgery.GetAndStoreTokens(context.HttpContext);
context.HttpContext.Response.Cookies.Append(
CookieName,
tokens.RequestToken,
new CookieOptions { HttpOnly = false });
}
}
}
/* HomeController */
[ServiceFilter(typeof(AngularAntiForgeryTokenAttribute), IsReusable = true)]
public IActionResult Index()
{
return View();
}
/* AccountController */
[HttpPost()]
[AllowAnonymous]
[ValidateAntiForgeryToken]
// Send new antiforgery token
[ServiceFilter(typeof(AngularAntiForgeryTokenAttribute), IsReusable = true)]
public async Task<IActionResult> Register([FromBody] RegisterViewModel model)
{
//...
return Json(new { });
}
Register the attribute in Startup, and configure Antiforgery service to read the request token form "X-XSRF-TOKEN" header.
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddScoped<AngularAntiForgeryTokenAttribute>();
services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
});
}
}
I think you need to make custom AntiForgeryValidationToken attribute that supports sending token via header instead of form values. Then add token to header of every request from your Angular2 app to your api. Example here How do you set global custom headers in Angular2?
To validate the token from a header you can use something like this:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class ValidateHeaderAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException(nameof(filterContext));
}
var httpContext = filterContext.HttpContext;
if (httpContext.Request.Headers["__RequestVerificationToken"] == null)
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
httpContext.Response.StatusDescription = "RequestVerificationToken missing.";
filterContext.Result = new JsonResult
{
Data = new { ErrorMessage = httpContext.Response.StatusDescription },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
return;
}
var cookie = httpContext.Request.Cookies[System.Web.Helpers.AntiForgeryConfig.CookieName];
System.Web.Helpers.AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
}
}
Then you just add [ValidateHeaderAntiForgeryToken] on the methods in your controller. Note though, this is from a MVC 5, ASP.NET 4.5.2 project, so you may have to alter it slightly to adjust to .NET Core. Also I modified this to return a JSON result if the token is missing, you can remove that part if you don't handle the error response and output it to the user.
Credits for the core part of this attribute goes to: https://nozzlegear.com/blog/send-and-validate-an-asp-net-antiforgerytoken-as-a-request-header
The hard part is how to generate the AntiForgeryToken without using #Html.AntiForgeryToken() in pure Angular 2 application (without access to .cshtml files). I'm looking for an answer to that as well.

Post JSON Object using httpClient windows Phone 8.1

I'm trying to post a json Object to a web api project from a windows phone app but I'm still getting 404 error. For the post method, I'm using that code:
Mail mailToCheck = new Mail();
try
{
mailToCheck.MailProfil = TxtBox_mail.Text.ToString();
string json = JsonConvert.SerializeObject(mailToCheck);
var httpClient = new System.Net.Http.HttpClient(new HttpClientHandler());
System.Net.Http.HttpResponseMessage response = await httpClient.PostAsync(new Uri("http://uri/api/Profil/CheckMail"), new StringContent(json));
var responseString = await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.HResult.ToString());
}
The method CheckMail on my conctroller:
[HttpPost]
[Route("api/Profil/CheckMail")]
public IHttpActionResult CheckMail([FromBody]Mail MailProfil)
{
if (MailProfil.MailProfil != null)
{
try
{
bool exists = Librairie.Profils.mailExists(MailProfil.MailProfil);
return Ok(exists);
}
catch(Exception ex)
{
return InternalServerError(ex);
}
}
else
{
return BadRequest();
}
}
The Mail object is exactly the same in the app as in the web api project. Does someone can tell me what I'm doing wrong here ?
Check some samples of HttpClient.PostAsync() here: https://monkeyweekend.wordpress.com/2014/10/23/how-to-send-text-json-or-files-using-httpclient-postasync/

Testing WebSecurity.Login() problems

I'm trying to test my ASP.NET MVC4 Application within Visual Studio and I am running into problems when testing WebSecurity.Login().
It seems to work perfectly when running my application but throws out an error when testing.
Method to test:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(HomeModels.LoginModel model)
{
if (ModelState.IsValid)
{
try
{
var username = model.Username;
var password = model.Password;
if (WebSecurity.Login(username, password, true))
{
if (Roles.Provider.IsUserInRole(username, "admin"))
{
return RedirectToAction("AdminHome");
}
else if (Roles.Provider.IsUserInRole(username, "user"))
{
return RedirectToAction("LoginSuccessful");
}
}
else
{
//String errorMessage = "Login was not successful.";
}
}
catch (MemberAccessException e)
{
ModelState.AddModelError("", e);
}
}
return View(model);
}
Test Method:
[TestMethod]
public void TestLoginAdminSuccessfulView()
{
HomeController controller = new HomeController();
Ecommerce.Models.HomeModels.LoginModel login = new Ecommerce.Models.HomeModels.LoginModel();
login.Username = "sgupta";
login.Password = "sgupta2189";
var result = (RedirectToRouteResult) controller.Login(login);
Assert.AreEqual("AdminHome", result.RouteName);
}
Error Message:
Test method EcommerceUnitTests.Controllers.HomeControllerTest.TestLoginAdminSuccessfulView threw exception:
System.InvalidOperationException: To call this method, the "Membership.Provider" property must be an instance of "ExtendedMembershipProvider".
Error Stack Trace:
WebMatrix.WebData.WebSecurity.VerifyProvider()
WebMatrix.WebData.WebSecurity.Login(String userName, String password, Boolean persistCookie)
Ecommerce.Controllers.HomeController.Login(LoginModel model)
EcommerceUnitTests.Controllers.HomeControllerTest.TestLoginAdminSuccessfulView()
copy the working web.config to app.config in the project containing your tests.
Make sure your Test project references assembly that is / contains your custom member provider.
If the main project is working, check what references it has.
I ended up restructuring it all and using ASP.NET's default membership provider.

Can I use ASP.NET MVC3 exclusively as a RESTful Web Service?

I'm building a READ ONLY sencha-touch app for our local church.
We use Vimeo to host all of our videos, and I'd like to integrate our Vimeo vids as well as our RSS feed into our web app.
The rest of the "content" in the app will be static "info" as well as a contact form.
My question is, is it kosher to ONLY use ASP.NET MVC3 (minus the "V") to drive the JSON to our web app?
Yes, this works great. Just return a JsonResult.
Here is an example I am using in production:
public partial class StudentController : BaseController {
public StudentController(RESTContext portalContext)
: base(portalContext) { }
[HttpGet, Url("organizations/{organizationId?}/students")]
public virtual JsonResult List(Guid? organizationId) {
if (organizationId != RESTContext.OrganizationId)
throw new HttpNotAuthorizedException();
var query = RESTContext.GetQuery<IQuery<StudentCasesReport>>()
.Where(x => x.OrganizationId, organizationId)
.OrderBy(x => x.LastName, SortOrder.Ascending);
var cases = query.Execute(IsolationLevel.ReadUncommitted);
return Json(cases, JsonRequestBehavior.AllowGet);
}
[HttpGet, Url("organizations/{organizationId?}/students/{studentId?}")]
public virtual JsonResult Get(Guid? organizationId, Guid? studentId) {
if (studentId.IsNull())
throw new HttpNotFoundExecption();
if (organizationId != RESTContext.OrganizationId)
throw new HttpNotModifiedException();
var query = RESTContext.GetQuery<IQuery<StudentCasesReport>>()
.Where(x => x.OrganizationId, organizationId)
.Where(x => x.StudentCaseId, studentId)
.OrderBy(x => x.LastName, SortOrder.Ascending);
var cases = query.Execute(IsolationLevel.ReadUncommitted).FirstOrDefault();
if (cases.IsNull())
throw new HttpNotFoundExecption();
return Json(cases, JsonRequestBehavior.AllowGet);
}
}