I'm trying to send a post request contain data and image file. but when I send uing my code below, I getting an error. Please see my code below for on client side.
public async Task<HttpContent> PostRequestAsync(string requestUri)
{
string jsonString = string.Empty;
StringContent stringJsonContent = default(StringContent);
HttpResponseMessage requestResponse = new HttpResponseMessage();
try
{
stringJsonContent = new StringContent(jsonString, Encoding.UTF8, "application/json");
requestResponse = await this.httpClient.PostAsync(requestUri, stringJsonContent);
if (requestResponse.IsSuccessStatusCode)
{
return requestResponse?.Content;
}
else if (requestResponse.StatusCode == HttpStatusCode.InternalServerError)
{
}
else if (requestResponse.StatusCode == HttpStatusCode.Unauthorized)
{
}
}
catch (Exception ex)
{
throw ex.InnerException;
}
return requestResponse?.Content;
}
}
and on WebAPI the controller looks below
[HttpPost]
public async Task<ActionResult> UpdateProfile([FromForm] UpdateProfile updateProfile)
Model is
public class UpdateProfile:BaseModel
{
public string firstName { get; set; }
public string lastName { get; set; }
public IFormFile Image { get; set; }
}
but in POSTMAN I'm successfully upload the file using below, so that I have a feeling the there's wrong with my code in client side. Anyone can suggest what I need to add on my code to work? I'm getting an error and not able to send the request.
In your client code, you don’t use the form object to transmit data. StringContent stores the value of the form instead of the key. You can use the MultipartFormDataContent object to transfer all forms and files. In addition, I give an example code.
The code in client.
class Program
{
static async Task Main(string[] args)
{
await PostRequestAsync(#"D:\upload\1.jpg", new HttpClient(), "https://localhost:44370/api/UpdateProfile");
}
public static async Task<string> PostRequestAsync(string filePath,HttpClient _httpClient,string _url)
{
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
if (!File.Exists(filePath))
{
throw new FileNotFoundException($"File [{filePath}] not found.");
}
//Create form
using var form = new MultipartFormDataContent();
var bytefile = AuthGetFileData(filePath);
var fileContent = new ByteArrayContent(bytefile);
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(fileContent, "Image", Path.GetFileName(filePath));
//the other data in form
form.Add(new StringContent("Mr."), "firstName");
form.Add(new StringContent("Loton"), "lastName");
form.Add(new StringContent("Names--"), "Name");
var response = await _httpClient.PostAsync($"{_url}", form);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
return responseContent;
}
//Convert file to byte array
public static byte[] AuthGetFileData(string fileUrl)
{
using (FileStream fs = new FileStream(fileUrl, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
byte[] buffur = new byte[fs.Length];
using (BinaryWriter bw = new BinaryWriter(fs))
{
bw.Write(buffur);
bw.Close();
}
return buffur;
}
}
}
The action in WebApi
[ApiController]
[Route("[controller]")]
public class ApiController:Controller
{
[HttpPost("get")]
public string get([FromForm]UpdateProfile updateProfile)
{
return "get";
}
[HttpPost("UpdateProfile")]
public async Task<ActionResult> UpdateProfile([FromForm] UpdateProfile updateProfile)
{
return Json("The result data ");
}
}
The model
public class UpdateProfile : BaseModel
{
public string firstName { get; set; }
public string lastName { get; set; }
public IFormFile Image { get; set; }
}
public class BaseModel
{
public string Name { get; set; }
}
result:
Related
Suppose I have thousands of files in Azure blob Storage and I want to get one page at a time (it is not good idea to load entire pages). But I couldn't get any idea how to proceed.
I tried like this : List blobs with Azure Storage client libraries.
This is my code :
public async Task<BlobPageDto> GetBlobPageAsync
(string containerName, int? segmentSize, string? continuationToken)
{
var blobPage = new BlobPageDto();
try
{
BlobClient? blobClient = null;
var client = new BlobContainerClient(_connectionString, containerName);
await client.CreateIfNotExistsAsync();
// Call the listing operation and return pages of the specified size.
var resultSegment = client.GetBlobsAsync()
.AsPages(continuationToken, segmentSize);
await foreach (var page in resultSegment)
{
var blobItems = new List<BlobItemDto>();
foreach (var item in page.Values)
{
blobClient = client.GetBlobClient(item.Name);
string blobUrl = blobClient.Uri.ToString();
blobItems.Add(
new()
{
Name = item.Name,
Url = blobUrl
});
}
blobPage = new() { BlobItems = blobItems, ContinuationToken = page.ContinuationToken };
break; //to get one page
}
}
catch (RequestFailedException e)
{
}
return blobPage;
}
BlobItemDto.cs
public class BlobItemDto
{
public string Name { get; set; } = default!;
public string Url { get; set; } = default!;
}
BlobPageDto.cs
public class BlobPageDto
{
public IEnumerable<BlobItemDto>? BlobItems { get; set; }
public string? ContinuationToken { get; set; }
}
Update:
From above code How I can achieve the pagination like this (since by using ContinuationToken I can only move forward):
Microsoft provides a service to analyze text data called Text Analytics Cognitive Service.
Is it possible to use this service with local database? i.e. not in Azure
I work with some large databases and as for me it can be interesting to use it for:
Language detection
Key phrase extraction
Named Entity recognition
Sentiment analysis
Once you pull your data that you would like to detect its language
from your local database, you just need to fetch it then just pass in
below method. It would analysis your value in response.
API Access Keys:
private static readonly string endpointKey = "YourEndPonitKey";
private static readonly string endpoint = "https://YourServiceURL.cognitiveservices.azure.com/text/analytics/v2.1/languages";
Code Snippet:
public async Task<object> DetectLanguageAsync(string InputFromDbOrUser)
{
try
{
DetectedLanguageResponseModel ObjDitectedLanguageResponse = new DetectedLanguageResponseModel();
//Create laguage detection request param
RequestModel objRequestModel = new RequestModel();
objRequestModel.id = "1";
objRequestModel.text = InputFromDbOrUser;
//Made Document List
List<RequestModel> Objdocuments = new List<RequestModel>();
Objdocuments.Add(objRequestModel);
//Bind Request Model
LanguageDetection objRequestList = new LanguageDetection();
objRequestList.documents = Objdocuments;
// Bind and Serialize Request Object
var serializedObject = JsonConvert.SerializeObject(objRequestList);
// Call Language Detection API
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(endpoint);
request.Content = new StringContent(serializedObject, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", endpointKey);
var response = await client.SendAsync(request);
//Check status code and retrive response
if (response.IsSuccessStatusCode)
{
ResponseModel objResponse = JsonConvert.DeserializeObject<ResponseModel>(await response.Content.ReadAsStringAsync());
//Check Response List
foreach (var item in objResponse.documents)
{
//Checkings Empty Response and Return to Caller
if (objResponse.documents != null)
{
ObjDitectedLanguageResponse.Language = objResponse.documents[0].detectedLanguages[0].name;
return ObjDitectedLanguageResponse;
}
else
{
return "Sorry, I am not able to find a related topic! Would you like me to Bing Search?";
}
}
}
else
{
var result_string = await response.Content.ReadAsStringAsync();
return result_string;
}
}
return ObjDitectedLanguageResponse;
}
catch (Exception ex)
{
throw new NotImplementedException(ex.Message, ex.InnerException);
}
}
Class Used:
public class DetectedLanguage
{
public string name { get; set; }
public string iso6391Name { get; set; }
}
public class DetectedLanguageResponseModel
{
public dynamic Language { get; set; }
}
public class LanguageDetection
{
public List<RequestModel> documents { get; set; }
}
public class RequestModel
{
public string id { get; set; }
public string text { get; set; }
}
public class ResponseDocument
{
public string id { get; set; }
public List<DetectedLanguage> detectedLanguages { get; set; }
}
public class ResponseModel
{
public List<ResponseDocument> documents { get; set; }
public List<object> errors { get; set; }
}
Note: The current limit is 5,120 characters for each document; if you need to analyze larger documents, you can break them up into
smaller chunks for more you could refer official document
Hope that would help. If you need more implementation assistance please have a look on here
I have SharePoint List which content a Reference No. It'd URL look like this:
https://xyz.sharepoint.com/sites/site_name/Lists/List_name/AllItems.aspx
This List content ref no. I am trying to insert this data in the list.
{
"Optimum_x0020_Case_x0020_Reference": "000777"
}
This is url I am posting the data.
https://graph.microsoft.com/v1.0/sites/xyz.sharepoint.com:/sites/site_name:/lists/List_names/items
But I am getting this error:
error": {
"code": "accessDenied",
"message": "The caller does not have permission to perform the action.",
How to solve this? Using the access I am able to create folder, sub folder and Update meta data for other document.
What is the context of what you are doing this with? Is it an app that you are using? Are you inserting data on a already existing listitem or a new item?
This is the code I had to use for my UWP App. I'm not sure if this will help you or not, but it should give you a little guidance I hope. Creating the dictionary and figuring out the XML structure were the keys things I had to piece together to get my code to work.
I declared my scopes in my App.xaml.cs
public static string[] scopes = new string[] { "user.ReadWrite", "Sites.ReadWrite.All", "Files.ReadWrite.All" };
I have a submit button that I use on my MainPage
private async void SubmitButton_Click(object sender, RoutedEventArgs e)
{
var (authResult, message) = await Authentication.AquireTokenAsync();
if (authResult != null)
{
await SubmitDataWithTokenAsync(submiturl, authResult.AccessToken);
}
}
This calls the AquireToken which I have in a class file:
public static async Task<(AuthenticationResult authResult, string message)> AquireTokenAsync()
{
string message = String.Empty;
string[] scopes = App.scopes;
AuthenticationResult authResult = null;
message = string.Empty;
//TokenInfoText.Text = string.Empty;
IEnumerable<IAccount> accounts = await App.PublicClientApp.GetAccountsAsync();
IAccount firstAccount = accounts.FirstOrDefault();
try
{
authResult = await App.PublicClientApp.AcquireTokenSilentAsync(scopes, firstAccount);
}
catch (MsalUiRequiredException ex)
{
// A MsalUiRequiredException happened on AcquireTokenSilentAsync. This indicates you need to call AcquireTokenAsync to acquire a token
System.Diagnostics.Debug.WriteLine($"MsalUiRequiredException: {ex.Message}");
try
{
authResult = await App.PublicClientApp.AcquireTokenAsync(scopes);
}
catch (MsalException msalex)
{
message = $"Error Acquiring Token:{System.Environment.NewLine}{msalex}";
}
}
catch (Exception ex)
{
message = $"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}";
}
return (authResult,message);
}
I had created another class for my SharePointList
public class SharePointListItems
{
public class Lookup
{
public string SerialNumber { get; set; }
public string id { get; set; }
public override string ToString()
{
return SerialNumber;
}
}
public class Value
{
public Lookup fields { get; set; }
}
public class Fields
{
[JsonProperty("#odata.etag")]
public string ODataETag { get; set; }
public string ParameterA { get; set; }
public string ParameterB { get; set; }
public string ParameterC { get; set; }
}
public class RootObject
{
[JsonProperty("#odata.context")]
public string ODataContext { get; set; }
[JsonProperty("#odata.etag")]
public string ODataETag { get; set; }
[JsonProperty("fields#odata.context")]
public string FieldsODataContext { get; set; }
public Fields Fields { get; set; }
}
}
I used this class to create a dictionary for submitting my data to SharePoint.
public async Task<string> SubmitDataWithTokenAsync(string url, string token)
{
var httpClient = new HttpClient();
HttpResponseMessage response;
try
{
var root = new
{
fields = new Dictionary<string, string>
{
// The second string are public static strings that I
// I declared in my App.xaml.cs because of the way my app
// is set up.
{ "ParameterA", App.ParameterA },
{ "ParameterB", App.ParameterB },
{ "ParameterC", App.ParameterC },
}
};
var s = new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat };
var content = JsonConvert.SerializeObject(root, s);
var request = new HttpRequestMessage(HttpMethod.Post, url);
//Add the token in Authorization header
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent(content, Encoding.UTF8, "application/json");
response = await httpClient.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
catch (Exception ex)
{
return ex.ToString();
}
}
And my submiturl is defined:
public static string rooturl = "https://graph.microsoft.com/v1.0/sites/xxxxxx.sharepoint.com,495435b4-60c3-49b7-8f6e-1d262a120ae5,0fad9f67-35a8-4c0b-892e-113084058c0a/";
string submiturl = rooturl + "lists/18a725ac-83ef-48fb-a5cb-950ca2378fd0/items";
You can also look at my posted question on a similar topic here.
I am trying to implement service gateway pattern according to Service Gateway tutorial to support in-process handing via InProcessServiceGateway and external calling via JsonServiceClient in case ServiceStack service is deployed standalone. I use ServiceStack 4.5.8 version.
Validation feature works fine, but with InProcessServiceGateway, the failed validation throws ValidationException which directly results in a ServiceStack.FluentValidation.ValidationException in the client rather than populating ResponseStatus property of MyResponseDto. And I also tried GlobalRequestFilters and ServiceExceptionHandlers, both of them seem to work fine to capture ValidationException only with JsonHttpClient but InProcessServiceGateway.
Is there any way to make ValidationException thrown by InProcessServiceGateway captured and translated into Dto's ResponseStatus? Thanks.
My AppHost:
//Register CustomServiceGatewayFactory
container.Register<IServiceGatewayFactory>(x => new CustomServiceGatewayFactory()).ReusedWithin(ReuseScope.None);
//Validation feature
Plugins.Add(new ValidationFeature());
//Note: InProcessServiceGateway cannot reach here.
GlobalRequestFilters.Add((httpReq, httpRes, requestDto) =>
{
...
});
//Note: InProcessServiceGateway cannot reach here.
ServiceExceptionHandlers.Add((httpReq, request, ex) =>
{
...
});
My CustomServiceGatewayFactory:
public class CustomServiceGatewayFactory : ServiceGatewayFactoryBase
{
private IRequest _req;
public override IServiceGateway GetServiceGateway(IRequest request)
{
_req = request;
return base.GetServiceGateway(request);
}
public override IServiceGateway GetGateway(Type requestType)
{
var standaloneHosted = false;
var apiBaseUrl = string.Empty;
var apiSettings = _req.TryResolve<ApiSettings>();
if (apiSettings != null)
{
apiBaseUrl = apiSettings.ApiBaseUrl;
standaloneHosted = apiSettings.StandaloneHosted;
}
var gateway = !standaloneHosted
? (IServiceGateway)base.localGateway
: new JsonServiceClient(apiBaseUrl)
{
BearerToken = _req.GetBearerToken()
};
return gateway;
}
}
My client base controller (ASP.NET Web API):
public virtual IServiceGateway ApiGateway
{
get
{
var serviceGatewayFactory = HostContext.AppHost.TryResolve<IServiceGatewayFactory>();
var serviceGateway = serviceGatewayFactory.GetServiceGateway(HttpContext.Request.ToRequest());
return serviceGateway;
}
}
My client controller action (ASP.NET Web API):
var response = ApiGateway.Send<UpdateCustomerResponse>(new UpdateCustomer
{
CustomerGuid = customerGuid,
MobilePhoneNumber = mobilePhoneNumber
ValidationCode = validationCode
});
if (!response.Success)
{
return this.Error(response, response.ResponseStatus.Message);
}
My UpdateCustomer request DTO:
[Route("/customers/{CustomerGuid}", "PUT")]
public class UpdateCustomer : IPut, IReturn<UpdateCustomerResponse>
{
public Guid CustomerGuid { get; set; }
public string MobilePhoneNumber { get; set; }
public string ValidationCode { get; set; }
}
My UpdateCustomerValidator:
public class UpdateCustomerValidator : AbstractValidator<UpdateCustomer>
{
public UpdateCustomerValidator(ILocalizationService localizationService)
{
ValidatorOptions.CascadeMode = CascadeMode.StopOnFirstFailure;
RuleFor(x => x.ValidationCode)
.NotEmpty()
.When(x => !string.IsNullOrWhiteSpace(x.MobilePhoneNumber))
.WithErrorCode(((int)ErrorCode.CUSTOMER_VALIDATIONCODE_EMPTY).ToString())
.WithMessage(ErrorCode.CUSTOMER_VALIDATIONCODE_EMPTY.GetLocalizedEnum(localizationService, Constants.LANGUAGE_ID));
}
}
My UpdateCustomerResponse DTO:
public class UpdateCustomerResponse
{
/// <summary>
/// Return true if successful; return false, if any error occurs.
/// </summary>
public bool Success { get; set; }
/// <summary>
/// Represents error details, populated only when any error occurs.
/// </summary>
public ResponseStatus ResponseStatus { get; set; }
}
ServiceStack 4.5.8's InProcessServiceGateway source code:
private TResponse ExecSync<TResponse>(object request)
{
foreach (var filter in HostContext.AppHost.GatewayRequestFilters)
{
filter(req, request);
if (req.Response.IsClosed)
return default(TResponse);
}
if (HostContext.HasPlugin<ValidationFeature>())
{
var validator = ValidatorCache.GetValidator(req, request.GetType());
if (validator != null)
{
var ruleSet = (string)(req.GetItem(Keywords.InvokeVerb) ?? req.Verb);
var result = validator.Validate(new ValidationContext(
request, null, new MultiRuleSetValidatorSelector(ruleSet)) {
Request = req
});
if (!result.IsValid)
throw new ValidationException(result.Errors);
}
}
var response = HostContext.ServiceController.Execute(request, req);
var responseTask = response as Task;
if (responseTask != null)
response = responseTask.GetResult();
return ConvertToResponse<TResponse>(response);
}
ServiceStack's Service Gateways now convert validation exceptions into WebServiceExceptions from this commit which is available from v4.5.13 that's now available on MyGet.
I getting error null reference exception while trying to pass data to view model
ViewModel
public class AccommodationApplicationViewModel
{
public AccommodationApplicationViewModel() { }
public PropertyRentingApplication _RentingApplicationModel { get; set; }
public PropertyRentingPrice _PropertyRentingPriceModel { get; set; }
}
Controller Method
[Authorize]
[HttpGet]
public ActionResult ApplyForAccommodation()
{
int _studentEntityID = 0;
//PropertyRentingApplication PropertyRentingApplicationModel = new PropertyRentingApplication();
AccommodationApplicationViewModel PropertyRentingApplicationModel = new AccommodationApplicationViewModel();
if (User.Identity.IsAuthenticated)
{
_studentEntityID = _studentProfileServices.GetStudentIDByIdentityUserID(User.Identity.GetUserId());
if (_studentEntityID != 0)
{
bool StudentCompletedProfile = _studentProfileServices.GetStudentDetailedProfileStatusByID(_studentEntityID);
if (StudentCompletedProfile)
{
PropertyRentingApplicationModel._RentingApplicationModel.StudentID = _studentEntityID;
PropertyRentingApplicationModel._RentingApplicationModel.DateOfApplication = DateTime.Now;
var s = "dd";
ViewBag.PropertyTypes = new SelectList(_propertyManagementServices.GetAllPropertyType(), "PropertyTypeID", "Title");
// ViewBag.PropertyRentingPrise = _propertyManagementServices.GetAllPropertyRentingPrice();
return PartialView("ApplyForAccommodation_partial", PropertyRentingApplicationModel);
}
else
{
return Json(new { Response = "Please Complete Your Profile Complete Before Making Request For Accommodation", MessageStatus ="IncompletedProfile"}, JsonRequestBehavior.AllowGet);
}
}
return Json(new { Response = "User Identification Fail!", MessageStatus = "IdentificationFail" }, JsonRequestBehavior.AllowGet);
}
return RedirectToAction("StudentVillageHousing", "Home");
}
}
You haven't initialized either _RentingApplicationModel nor _PropertyRentingPriceModel. The easiest solution is to simply initialize these properties in your constructor for AccommodationApplicationViewModel:
public AccommodationApplicationViewModel()
{
_RentingApplicationModel = new PropertyRentingApplication();
_PropertyRentingPriceModel = new PropertyRentingPrice();
}
Then, you should be fine.