How to trigger App Center Push from my asp.net Web API? - asp.net-web-api

I'm making an android Xamarin.Android. I finished the android application and now I want to add remote push notifications based on my item condition in my database that can accessed from ASP.Net Web Api.
I succeeded sent notifications from App Center Push to my application. I already authorized the App Center Client and now can access the app center api. I'm planning to merge the app center api to my asp.net web api if possible. But I don't know where to start it.
Should I put the app center action to my controller (I don't know if its working or not) or there's another way?
here's my controller:
public class InventoriesController : ApiController
{
private InventoryRepository _inventoryRepository;
public InventoriesController()
{
_inventoryRepository = new InventoryRepository();
}
// GET: api/Categories
public IHttpActionResult GetInventories()
{
IEnumerable<InventoryViewModel> inv = _inventoryRepository.GetAll().ToList().Select(e=> new InventoryViewModel(e)).ToList();
return Ok(inv);
}
// GET: api/Categories/5
[ResponseType(typeof(InventoryViewModel))]
public IHttpActionResult GetInventory(Guid id)
{
InventoryViewModel inventory = new InventoryViewModel (_inventoryRepository.GetSingle(e => e.Id == id));
if (inventory == null)
{
return NotFound();
}
return Ok(inventory);
}
// PUT: api/Categories/5
[ResponseType(typeof(void))]
public IHttpActionResult PutInventory(Guid id, InventoryViewModel inventory)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != inventory.Id)
{
return BadRequest();
}
try
{
_inventoryRepository.Edit(inventory.ToModel());
}
catch (DbUpdateConcurrencyException)
{
if (!InventoryExist(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/Categories
[ResponseType(typeof(InventoryViewModel))]
public IHttpActionResult PostInventory(InventoryViewModel inventory)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
_inventoryRepository.Add(inventory.ToModel());
}
catch (DbUpdateException)
{
if (InventoryExist(inventory.Id))
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtRoute("DefaultApi", new { id = inventory.Id }, inventory);
}
// DELETE: api/Categories/5
[ResponseType(typeof(Inventory))]
public async Task<IHttpActionResult> DeleteInventory(Guid id)
{
Inventory inventory = _inventoryRepository.GetSingle(e => e.Id == id);
if (inventory == null)
{
return NotFound();
}
await _inventoryRepository.DeleteAsync(inventory);
return Ok(inventory);
}
private bool InventoryExist(Guid id)
{
IQueryable<Inventory> inv = _inventoryRepository.GetAll();
return inv.Count(e => e.Id == id) > 0;
}
And this is my model:
public class InventoryViewModel
{
public Guid Id { get; set; }
public int Quantity { get; set; }
public DateTime ExpirationDate { get; set; }
public bool IsDeleted { get; set; }
public bool IsConsumed { get; set; }
public decimal Price { get; set; }
public string ItemName { get; set; }
public Guid ProductId { get; set; }
public Guid StorageId { get; set; }
public string AddedUserId { get; set; }
public Inventory ToModel()
{
return new Inventory
{
Id = (Id == Guid.Empty) ? Guid.NewGuid() : Id,
ExpirationDate = ExpirationDate,
Price = Price,
ProductId=ProductId,
StorageId=StorageId,
ItemName=ItemName,
IsDeleted=IsDeleted,
IsConsumed=IsConsumed,
AddedUserId = AddedUserId,
};
}
public InventoryViewModel()
{
}
public InventoryViewModel(Inventory i)
{
this.Id = i.Id;
this.ExpirationDate = i.ExpirationDate;
this.Price = i.Price;
this.ProductId = i.ProductId;
this.StorageId = i.StorageId;
this.ItemName = i.ItemName;
this.AddedUserId = i.AddedUserId;
}
}
I want to make the app center send notification based on Expired Date on my Inventories model and AddedUserId. So its my web self made web api who send the notification to my apps.
I read this documentation: [https://learn.microsoft.com/en-us/appcenter/push/pushapi][1] but still don't know where I have to write in my Web Api.
Hope someone here can help me.
Thanks in advance :)

You can find detail here in appcenter REST API documentation
https://learn.microsoft.com/en-us/appcenter/push/rest-api
Appcenter REST API swagger: https://openapi.appcenter.ms/

Related

How insert multiple value in Intermediate table through API

I use to add value from the VUEJS where write code like this.
<multiselect v-model="schoolTypeform.schoolTypeId" :options="SchoolTypes" :multiple="true" :close-on-select="false" :clear-on-select="false" :preserve-search="true" placeholder="Pick School Type" label="name" track-by="name" :preselect-first="true">
and the JS code for this is written like this:
async addSchool() {
this.isbtnLoading = true;
this.isException = false;
await this.axios.post(this.school, this.form).then(response => {
this.addSchoolType(response.data);
})
},
async addSchoolType(id) {
this.isbtnLoading = true;
this.isException = false;
this.schoolTypeform.shoolId = id;
await this.axios.post(this.apiBasedUrl + '/SchoolsSchoolType', this.schoolTypeform).then(response => {
this.isbtnLoading = false;
});
Now my ER structure is given like this:
School:(Table1)
public partial class Schools
{
public Guid ID { get; set; }
public string Name{ get; set; }
// Navigation
public ICollection<SchoolsSchoolType> SchoolsSchoolTypes { get; set; }
}
SchoolType:(Table2)
public class SchoolType
{
public Guid Id { get; set; }
public string Name { get; set; }
//Navigation
public ICollection<SchoolsSchoolType> SchoolsSchoolTypes { get; set; }
}
SchoolsSchoolType (It is Intermediate table): Here the relation between the above is many to many.
public class SchoolsSchoolType
{
public Guid Id { get; set; }
public Guid ShoolId { get; set; }
public Schools Schools { get; set; }
public Guid SchoolTypeId { get; set; }
public SchoolType SchoolType { get; set; }
}
Here is repository method write for single value input, but I want to add here multiple value in the intermediates or junction table.
public async Task<Guid> CreateSchoolsAsync(SchoolsCreateVm schoolsCreateVm)
{
if (_GpsContext != null)
{
var schoolsEntity = new Schools()
{
ID = Guid.NewGuid(),
Name = schoolsCreateVm.Name,
SchoolsSchoolTypes = new List<SchoolsSchoolType>()
};
var schoolType = new SchoolType();
schoolsEntity.SchoolsSchoolTypes = new List<SchoolsSchoolType>
{
new SchoolsSchoolType
{
ShoolId =schoolsEntity.ID,
SchoolTypeId =schoolType.Id
}
};
return schoolsEntity.ID;
}
return Guid.Empty
}
Controller code is written here:
[HttpPost]
public async Task<IActionResult> PostSchool([FromBody]SchoolsCreateVm schoolsCreateVm)
{
var result = await _schoolsRepository.CreateSchoolsAsync(schoolsCreateVm);
if (result != null)
{
return Ok(result);
}
return NotFound();
}
Here is viewmodel used by me:
public class SchoolsCreateVm
{
public string Name { get; set; }
public List<Guid> SchoolTypeId{ get; set; } // List type of for intermediate table
public SchoolsCreateVm()
{
SchoolTypeId = new List<Guid>();
}
How can insert many schooltype for a single school in the intermediates(many to many) relation table through the VUEJS multiple selects.
Finally I am able to find the solution...
public async Task<Guid> CreateSchoolsAsync(SchoolsCreateVm schoolsCreateVm)
{
if (_GpsContext != null)
{
var schoolId = Guid.NewGuid();
var schoolsEntity = new Schools()
{
ID = schoolId, // 1--[1,2,3]
Name = schoolsCreateVm.Name,
};
// Here the code in which we can enter in the multiple table and Intermediate table
var SchoolsSchoolTypeList = new List<SchoolsSchoolType>();
foreach(var item in schoolsCreateVm.SchoolTypeId)
{
SchoolsSchoolTypeList.Add(new SchoolsSchoolType
{
Id = Guid.NewGuid(),
ShoolId = schoolId,
SchoolTypeId = item,
});
}
await _GpsContext.School.AddAsync(schoolsEntity);
_GpsContext.SchoolsSchoolTypes.AddRange(SchoolsSchoolTypeList);//Enter here for intermediate table that is 'SchoolsSchoolTypes'
await _GpsContext.SaveChangesAsync();
return schoolsEntity.ID;
}
return Guid.Empty;
}

How do I custom validate collections withing MVC5

I am building an MVC5 application and I have the following viewmodels:
public class UserPartyViewModel
{
public UserPartyViewModel()
{
Entitlements = new Collection<AssignedClaims>();
}
public Guid PartyID { get; set; }
public string PartyName { get; set; }
public ICollection<AssignedClaim> AssignedClaims{ get; set; }
}
public class AssignedClaims
{
public AssignedClaims()
{
ClaimValues = new Collection<AssignedClaimValue>();
}
public string Name { get; set; }
public int Max { get; set; }
public int Min { get; set; }
public ICollection<AssignedClaimValue> ClaimValues { get; set; }
}
public class AssignedClaimValue
{
public Guid ClaimValueID { get; set; }
public string ClaimValue { get; set; }
public bool Assigned { get; set; }
}
Contained in the UserPartyViewModel will always be an assignedclaim with a name of "Security" and the assignedclaimvalue with a claimvalue of "User"
If the ClaimValue of user is Assigned then I need to validate the rest of the model. If it is not then no further validation should take place.
Within AssignedClaims there is a min and max, these are the minimum and maximum number of assignedclaimvalues that should be Assigned.
I have tried to use AttributeValidate cannot stop it validating the rest of the model.
I have also looked at the IValidatableObject interface but also can't work out how to control the validation of the child collections depending on the User claim.
What's the best way to achieve this?
Found a solution which appears to do what I want:
public class UserPartyViewModel : IValidatableObject
{
public UserPartyViewModel()
{
Entitlements = new Collection<AssignedClaims>();
}
public string AccessLevel { get; set; }
public Guid PartyID { get; set; }
public string PartyName { get; set; }
public ICollection<AssignedClaims> Entitlements { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var isUser = Entitlements.Any(c => c.Name == "Security" && c.ClaimValues.Any(v => v.Assigned == true && v.ClaimValue == "User"));
if (isUser)
{
int i = 0;
foreach (var result in Entitlements)
{
yield return result.Validate(i++);
}
}
else
{
yield return ValidationResult.Success;
}
}
}
public class AssignedClaims
{
public AssignedClaims()
{
ClaimValues = new Collection<AssignedClaimValue>();
}
public string Name { get; set; }
public string Description { get; set; }
public int Max { get; set; }
public int Min { get; set; }
public ICollection<AssignedClaimValue> ClaimValues { get; set; }
public ValidationResult Validate(int item)
{
int min = Min;
int max = (ClaimValues.Count() < Max) ? ClaimValues.Count() : Max;
int assignedCount = ClaimValues.Where(i => i.Assigned == true).Count();
if (!(min <= assignedCount && assignedCount <= max))
{
string errMessage = String.Format("{2} should have between {0} and {1} Security Claims checked.", min, max, Name);
return new ValidationResult(errMessage, new[] { string.Format("Entitlements[{0}]", item) });
}
else
{
return ValidationResult.Success;
}
}
}
The only issue I had was trying to get the error messages appearing in the correct place. In my view for assignedclaims I added:
#Html.ValidationMessageFor(model => model, "", new { #class = "text-danger" })
and passed the iteration through to the validate function on assignedclaim to ensure it was added to the correct member.

How to use split in linq query?

I am trying to call the following query string but I am getting 'no data' message on the client-side - 'api/data?id=786,899&price_type=cvr'.
public HttpResponseMessage Get([FromUri] Query query)
{
var data = db.database_ICs.AsQueryable();
if (query.id!= null)
{
data = data.Where(c => query.id.Split(',').Contains(c.ID));
}
if (query.price_type != null)
{
data = data.Where(c => c.Cover == query.price_type);
}
if (!data.Any())
{
var message = string.Format("No data was found");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}
return Request.CreateResponse(HttpStatusCode.OK, data);
}
public class Query
{
public string id{ get; set; }
public string price_type { get; set; }
public Nullable<DateTime> startDate { get; set; }
public Nullable<DateTime> endDate{ get; set; }
}
Any help would be very much appreciated.
Many Thanks.
var data = db.database_ICs.AsQueryable();
if (!string.IsNullOrEmpty(query.id))
{
var ids = query.id.Split(',').ToList();
data = data.Where(c => ids.Contains(c.ID));
}
Assuming c.ID and ids elements are of the same type of course.
Edit: one way of checking if you have the querystring or not

Having issue while trying to pass two model to the same view at a time in mvc 3

I'm trying to create my profile type page for my simple blog site. I have two simple model class like this:
public class UserInfoModel
{
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
public class NewPost
{
public string PostTitle { get; set; }
public string PostStory { get; set; }
}
I have created a joint model class of user & post to pass to view like this:
public class UserPostModel
{
public UserInfoModel User { get; set; }
public NewPost Post { get; set; }
}
The methods I wrote to retrieve the user & post info are like this:
public int GetUserID(string _UserName)
{
using (var context = new TourBlogEntities1())
{
var UserID = from s in context.UserInfoes
where s.UserName == _UserName
select s.UserID;
return UserID.Single();
}
}
public UserInfo GetUserDetails(int _UserID)
{
using (var context = new TourBlogEntities1())
{
var UserDetails = (from s in context.UserInfoes
where s.UserID == _UserID
select s).Single();
return UserDetails;
}
}
public Post GetUserPosts(int _UserID)
{
using (var context = new TourBlogEntities1())
{
var entity = (from s in context.Posts
where s.UserID == _UserID
select s).Single();
return entity;
}
}
And finally I'm calling all my method from my controller action like this:
[Authorize]
public ActionResult MyProfile()
{
var Business = new Business();
var UserID=Business.GetUserID(User.Identity.Name);
var UserEntity=Business.GetUserDetails(UserID);
var PostEntity=Business.GetUserPosts(UserID);
var model = new UserPostModel();
model.User.UserName = UserEntity.UserName; // problem showing here
model.User.Email = UserEntity.Email;
model.Post.PostTitle = PostEntity.PostTitle;
model.Post.PostStory = PostEntity.PostStory;
return View("MyProfile",model);
}
A run time error showing like " object is not referenced to a object type or null object". I worked ok in a very similar way while passing single model. Whats I'm doing wrong here?
Modified your UserPostModel
public class UserPostModel
{
public UserPostModel()
{
User = new UserInfoModel();
Post = new Post();
}
public UserInfoModel User { get; set; }
public NewPost Post { get; set; }
}
NOTE: check each value before set to model it should not be null.

knockoutjs with mvc collection model binding

I'm using knockoutjs to render a collection of items. After allowing the user to do some inline editing I need to post the collection back to the server. However, the collection isn't being populated on the server because I'm not using the name="[0].Blah" naming convention. Does anyone know how to either render name attributes like this using knockoutjs OR how to create a model binder that will allow me to extract the values from the ValueProvider?
You can see a screenshot of the ValueProvider during debugging below.
http://i.imgur.com/zSU5Z.png
Here is my managed ViewModel:
public class FundLevelInvestmentUploadResult
{
public string FileName { get; set; }
public IList<FundLevelInvestmentViewModel> Items { get; set; }
public int NumberOfErrors { get; set; }
public bool ShowErrorsOnly { get; set; }
public FundLevelInvestmentUploadResult()
{
Items = new List<FundLevelInvestmentViewModel>();
}
}
Here is the managed class for "Items":
public class FundLevelInvestmentViewModel
{
private string _fund;
private string _fundType;
private string _date;
private string _netOfWaivedFees;
private string _waivedFees;
private string _bcip;
private string _fxRate;
public uint RowIndex { get; set; }
public int? DealCode { get; set; }
public bool DealCodeIsValid { get; set; }
public string Fund
{
get { return _fund; }
set { _fund = GetString(value); }
}
public bool FundIsValid { get; set; }
public string FundType
{
get { return _fundType; }
set { _fundType = GetString(value); }
}
public bool FundTypeIsValid { get; set; }
public string DateOfInvestment
{
get { return _date; }
set { _date = GetString(value); }
}
public bool DateOfInvestmentIsValid { get; set; }
public string NetOfWaivedFees
{
get { return _netOfWaivedFees; }
set { _netOfWaivedFees = GetString(value); }
}
public bool NetOfWaivedFeesIsValid { get; set; }
public string WaivedFee
{
get { return _waivedFees; }
set { _waivedFees = GetString(value); }
}
public bool WaivedFeeIsValid { get; set; }
public string BCIP
{
get { return _bcip; }
set { _bcip = GetString(value); }
}
public bool BCIPIsValid { get; set; }
public string ExchangeRateToUSD
{
get { return _fxRate; }
set { _fxRate = GetString(value); }
}
public bool ExchangeRateToUSDIsValid { get; set; }
public string FileName { get; set; }
private IList<string> _errors;
public IList<string> Errors
{
get { return _errors ?? (_errors = new List<string>());}
set { _errors = value; }
}
public bool Show { get; set; }
public FundLevelInvestmentViewModel()
{
Errors = new List<string>();
Show = true;
}
// knockoutjs is returning "null" instead of "" for a null object when calling ko.mapping.fromJS
private string GetString(string value)
{
if (value == "null")
return string.Empty;
return value;
}
}
Here is my knockout viewModel:
var viewModel = {
FileData: ko.observableArray([]),
validateFile: function (file, event) {
$.ajax({
type: 'post',
url: newUrl,
data: ko.mapping.toJS(file)
}).done(function (data) {
var newFile = ko.mapping.fromJS(data);
var index = file.Items.indexOf(file);
viewModel.FileData.replace(file, newFile);
});
}
};
If you are using version 2.1.0.0 or later of knockout you can render the name attribute as follows from an observable array.
<input data-bind='attr: { name: "Items["+$index()+"].DealCode"}' />

Resources